diff --git a/dashboard/src/components/dashboard/AircallDashboard.jsx b/dashboard/src/components/dashboard/AircallDashboard.jsx index dba16b5..e8146ae 100644 --- a/dashboard/src/components/dashboard/AircallDashboard.jsx +++ b/dashboard/src/components/dashboard/AircallDashboard.jsx @@ -168,18 +168,18 @@ const AgentPerformanceTable = ({ agents, onSort }) => { const SkeletonMetricCard = () => ( - - + +
- - + +
); const SkeletonChart = ({ type = "line" }) => ( -
+
{type === "bar" ? ( @@ -187,7 +187,7 @@ const SkeletonChart = ({ type = "line" }) => ( {[...Array(24)].map((_, i) => (
))} @@ -197,12 +197,12 @@ const SkeletonChart = ({ type = "line" }) => ( {[...Array(5)].map((_, i) => (
))}
( - - - - - + + + + + {[...Array(rows)].map((_, i) => ( - - - - - - + + + + + + ))} @@ -356,9 +356,13 @@ const AircallDashboard = () => { if (error) { return ( - - Error loading call data: {error} - + + +
+ Error loading call data: {error} +
+
+
); } @@ -372,7 +376,7 @@ const AircallDashboard = () => {
- - - Reason - Count - - - - {chartData.missedReasons.map((reason, index) => ( - - - {reason.reason} - - - {reason.count} - +
+
+ + + Reason + Count - ))} - -
+ + + {chartData.missedReasons.map((reason, index) => ( + + + {reason.reason} + + + {reason.count} + + + ))} + + +
)} diff --git a/dashboard/src/components/dashboard/AnalyticsDashboard.jsx b/dashboard/src/components/dashboard/AnalyticsDashboard.jsx index 5bb75d3..dd5bcc7 100644 --- a/dashboard/src/components/dashboard/AnalyticsDashboard.jsx +++ b/dashboard/src/components/dashboard/AnalyticsDashboard.jsx @@ -23,6 +23,8 @@ import { import { Loader2, TrendingUp, AlertCircle } from "lucide-react"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Skeleton } from "@/components/ui/skeleton"; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; // Add helper function for currency formatting const formatCurrency = (value, useFractionDigits = true) => { @@ -38,40 +40,42 @@ const formatCurrency = (value, useFractionDigits = true) => { // Add skeleton components const SkeletonChart = () => ( -
+
-
- {[...Array(5)].map((_, i) => ( -
- ))} + {/* Grid lines */} + {[...Array(5)].map((_, i) => (
-
- {[...Array(8)].map((_, i) => ( -
- ))} + ))} + {/* Y-axis labels */} +
+ {[...Array(5)].map((_, i) => ( + + ))} +
+ {/* X-axis labels */} +
+ {[...Array(6)].map((_, i) => ( + + ))} +
+ {/* Chart line */} +
+
+
-
- {[...Array(6)].map((_, i) => ( - - ))} -
); @@ -79,13 +83,13 @@ const SkeletonChart = () => ( const SkeletonStats = () => (
{[...Array(4)].map((_, i) => ( - + - + - - + + ))} @@ -95,7 +99,7 @@ const SkeletonStats = () => ( const SkeletonButtons = () => (
{[...Array(4)].map((_, i) => ( - + ))}
); @@ -109,12 +113,12 @@ const StatCard = ({ trendValue, colorClass = "text-gray-900 dark:text-gray-100", }) => ( - + - {title} + {title} {trend && ( -
{value}
+
{value}
{description && ( -
{description}
+
{description}
)}
@@ -252,19 +256,19 @@ export const AnalyticsDashboard = () => { const CustomTooltip = ({ active, payload, label }) => { if (active && payload && payload.length) { return ( - + -

+

{label instanceof Date ? label.toLocaleDateString() : label}

-
+
{payload.map((entry, index) => (
- {entry.name}: - + {entry.name}: + {entry.value.toLocaleString()}
@@ -282,24 +286,114 @@ export const AnalyticsDashboard = () => {
- - Analytics Overview - - {loading ? ( - - ) : ( - - )} +
+ + Analytics Overview + +
+
+ {loading ? ( + + ) : ( + <> + + + + + + + Daily Details +
+
+ {Object.entries(metrics).map(([key, value]) => ( + + ))} +
+
+
+
+
+ + + + Date + {metrics.activeUsers && ( + Active Users + )} + {metrics.newUsers && ( + New Users + )} + {metrics.pageViews && ( + Page Views + )} + {metrics.conversions && ( + Conversions + )} + + + + {data.map((day) => ( + + {formatXAxis(day.date)} + {metrics.activeUsers && ( + + {day.activeUsers.toLocaleString()} + + )} + {metrics.newUsers && ( + + {day.newUsers.toLocaleString()} + + )} + {metrics.pageViews && ( + + {day.pageViews.toLocaleString()} + + )} + {metrics.conversions && ( + + {day.conversions.toLocaleString()} + + )} + + ))} + +
+
+
+
+
+ + + )} +
{loading ? ( @@ -341,65 +435,65 @@ export const AnalyticsDashboard = () => {
) : null} -
- {loading ? ( - - ) : ( -
- - - - -
- )} +
+
+ + + + +
@@ -410,17 +504,19 @@ export const AnalyticsDashboard = () => { ) : !data.length ? (
- -
No analytics data available
-
Try selecting a different time range
+ +
No analytics data available
+
+ Try selecting a different time range +
) : ( -
+
{ } /> diff --git a/dashboard/src/components/dashboard/EventFeed.jsx b/dashboard/src/components/dashboard/EventFeed.jsx index 9302c3e..b90eb8b 100644 --- a/dashboard/src/components/dashboard/EventFeed.jsx +++ b/dashboard/src/components/dashboard/EventFeed.jsx @@ -148,24 +148,22 @@ const LoadingState = () => (
-
-
-
- -
-
- -
-
- - - -
+
+
+ +
+
+ +
+
+ + +
- - + +
))} @@ -174,14 +172,14 @@ const LoadingState = () => ( // Empty State Component const EmptyState = () => ( -
+
- +

No activity yet today

-

+

Recent activity will appear here as it happens

@@ -1402,18 +1400,18 @@ const EventFeed = ({ return ( - +
{title} {lastUpdate && ( - + Last updated {format(lastUpdate, "h:mm a")} )}
{!error && ( -
+
@@ -1421,7 +1419,7 @@ const EventFeed = ({ variant={activeEventTypes[METRIC_IDS.PLACED_ORDER] ? "default" : "outline"} size="sm" onClick={() => handleEventTypeClick(METRIC_IDS.PLACED_ORDER)} - className="h-8 w-8 p-0" + className="h-8 w-8 p-0 rounded-md" > @@ -1432,77 +1430,77 @@ const EventFeed = ({ - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + @@ -1511,7 +1509,7 @@ const EventFeed = ({ variant={activeEventTypes[METRIC_IDS.NEW_BLOG_POST] ? "default" : "outline"} size="sm" onClick={() => handleEventTypeClick(METRIC_IDS.NEW_BLOG_POST)} - className="h-8 w-8 p-0" + className="h-8 w-8 p-0 rounded-md" > @@ -1525,7 +1523,7 @@ const EventFeed = ({ )}
- {/* Order Property Filters - only show if not in error state */} + {/* Order Property Filters - update styling */} {!error && (
{counts.orderProperties.hasPreorder > 0 && ( @@ -1536,7 +1534,7 @@ const EventFeed = ({ orderFilters.hasPreorder ? 'bg-purple-800 text-purple-200 hover:bg-purple-700' : 'bg-purple-100 dark:bg-purple-900/20 text-purple-800 dark:text-purple-300 hover:bg-purple-100 dark:hover:bg-purple-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Pre-order ({counts.orderProperties.hasPreorder}) @@ -1549,7 +1547,7 @@ const EventFeed = ({ orderFilters.localPickup ? 'bg-green-800 text-green-200 hover:bg-green-700' : 'bg-green-100 dark:bg-green-900/20 text-green-800 dark:text-green-300 hover:bg-green-100 dark:hover:bg-green-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Local ({counts.orderProperties.localPickup}) @@ -1562,7 +1560,7 @@ const EventFeed = ({ orderFilters.isOnHold ? 'bg-blue-800 text-blue-200 hover:bg-blue-700' : 'bg-blue-100 dark:bg-blue-900/20 text-blue-800 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > On Hold ({counts.orderProperties.isOnHold}) @@ -1575,7 +1573,7 @@ const EventFeed = ({ orderFilters.onHoldReleased ? 'bg-green-800 text-green-200 hover:bg-green-700' : 'bg-green-100 dark:bg-green-900/20 text-green-800 dark:text-green-300 hover:bg-green-100 dark:hover:bg-green-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Hold Released ({counts.orderProperties.onHoldReleased}) @@ -1588,7 +1586,7 @@ const EventFeed = ({ orderFilters.hasDigiItem ? 'bg-indigo-800 text-indigo-200 hover:bg-indigo-700' : 'bg-indigo-100 dark:bg-indigo-900/20 text-indigo-800 dark:text-indigo-300 hover:bg-indigo-100 dark:hover:bg-indigo-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Digital ({counts.orderProperties.hasDigiItem}) @@ -1601,7 +1599,7 @@ const EventFeed = ({ orderFilters.hasNotions ? 'bg-yellow-800 text-yellow-200 hover:bg-yellow-700' : 'bg-yellow-100 dark:bg-yellow-900/20 text-yellow-800 dark:text-yellow-300 hover:bg-yellow-100 dark:hover:bg-yellow-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Notions ({counts.orderProperties.hasNotions}) @@ -1614,7 +1612,7 @@ const EventFeed = ({ orderFilters.hasGiftCard ? 'bg-pink-800 text-pink-200 hover:bg-pink-700' : 'bg-pink-100 dark:bg-pink-900/20 text-pink-800 dark:text-pink-300 hover:bg-pink-100 dark:hover:bg-pink-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > eGift Card ({counts.orderProperties.hasGiftCard}) @@ -1627,7 +1625,7 @@ const EventFeed = ({ orderFilters.stillOwes ? 'bg-red-800 text-red-200 hover:bg-red-700' : 'bg-red-100 dark:bg-red-900/20 text-red-800 dark:text-red-300 hover:bg-red-100 dark:hover:bg-red-900/20' - } cursor-pointer`} + } cursor-pointer rounded-md`} > Owes ({counts.orderProperties.stillOwes}) @@ -1641,7 +1639,7 @@ const EventFeed = ({ {loading && !events.length ? ( ) : error ? ( - + Error @@ -1649,17 +1647,7 @@ const EventFeed = ({ ) : !filteredEvents || filteredEvents.length === 0 ? ( -
-
- -
-

- No activity yet today -

-

- Recent activity will appear here as it happens -

-
+ ) : (
{filteredEvents.map((event) => ( diff --git a/dashboard/src/components/dashboard/GorgiasOverview.jsx b/dashboard/src/components/dashboard/GorgiasOverview.jsx index 022161c..99c2ade 100644 --- a/dashboard/src/components/dashboard/GorgiasOverview.jsx +++ b/dashboard/src/components/dashboard/GorgiasOverview.jsx @@ -168,13 +168,13 @@ const SkeletonMetricCard = () => (
- +
- - + +
- +
@@ -184,19 +184,19 @@ const TableSkeleton = () => ( - - - - + + + + {[...Array(5)].map((_, i) => ( - - - - + + + + ))} @@ -326,13 +326,23 @@ const GorgiasOverview = () => { console.log('Processed agents:', agents); - if (error) return

Error: {error}

; + if (error) { + return ( + + +
+ {error} +
+
+
+ ); + } return ( - +
-

+

Customer Service

@@ -414,180 +424,182 @@ const GorgiasOverview = () => { loading={loading} />
+
+ +
+
+ +
+
+ +
+
+ +
)} - - {/* Satisfaction & Efficiency */} -
- -
-
- -
-
- -
-
- -
{/* Channel Distribution */} -
-
+ +

Channel Distribution

-
- {loading ? ( - - ) : ( -
- - - Channel - Total - % - Change - - - - {channels - .sort((a, b) => b.total - a.total) - .map((channel, index) => ( - - - {channel.name} - - - {channel.total} - - - {channel.percentage}% - - 0 - ? "text-green-600 dark:text-green-500" - : channel.delta < 0 - ? "text-red-600 dark:text-red-500" - : "dark:text-gray-300" - }`} - > -
- {channel.delta !== 0 && ( - <> - {channel.delta > 0 ? ( - - ) : ( - - )} - {Math.abs(channel.delta)}% - - )} -
-
-
- ))} -
-
- )} -
+ + + {loading ? ( + + ) : ( + + + + Channel + Total + % + Change + + + + {channels + .sort((a, b) => b.total - a.total) + .map((channel, index) => ( + + + {channel.name} + + + {channel.total} + + + {channel.percentage}% + + 0 + ? "text-green-600 dark:text-green-500" + : channel.delta < 0 + ? "text-red-600 dark:text-red-500" + : "text-muted-foreground" + }`} + > +
+ {channel.delta !== 0 && ( + <> + {channel.delta > 0 ? ( + + ) : ( + + )} + {Math.abs(channel.delta)}% + + )} +
+
+
+ ))} +
+
+ )} +
+ {/* Agent Performance */} -
-
+ +

Agent Performance

-
- {loading ? ( - - ) : ( - - - - Agent - Closed - Rating - Change - - - - {agents - .filter((agent) => agent.name !== "Unassigned") - .map((agent, index) => ( - - - {agent.name} - - - {agent.closed} - - - {agent.rating ? `${agent.rating}/5` : "-"} - - 0 - ? "text-green-600 dark:text-green-500" - : agent.delta < 0 - ? "text-red-600 dark:text-red-500" - : "dark:text-gray-300" - }`} - > -
- {agent.delta !== 0 && ( - <> - {agent.delta > 0 ? ( - - ) : ( - - )} - {Math.abs(agent.delta)}% - - )} -
-
-
- ))} -
-
- )} -
+ + + {loading ? ( + + ) : ( + + + + Agent + Closed + Rating + Change + + + + {agents + .filter((agent) => agent.name !== "Unassigned") + .map((agent, index) => ( + + + {agent.name} + + + {agent.closed} + + + {agent.rating ? `${agent.rating}/5` : "-"} + + 0 + ? "text-green-600 dark:text-green-500" + : agent.delta < 0 + ? "text-red-600 dark:text-red-500" + : "text-muted-foreground" + }`} + > +
+ {agent.delta !== 0 && ( + <> + {agent.delta > 0 ? ( + + ) : ( + + )} + {Math.abs(agent.delta)}% + + )} +
+
+
+ ))} +
+
+ )} +
+
diff --git a/dashboard/src/components/dashboard/MetaCampaigns.jsx b/dashboard/src/components/dashboard/MetaCampaigns.jsx index 6998abf..635b104 100644 --- a/dashboard/src/components/dashboard/MetaCampaigns.jsx +++ b/dashboard/src/components/dashboard/MetaCampaigns.jsx @@ -84,34 +84,26 @@ const summaryCard = (label, value, options = {}) => { ); }; -const MetricCell = ({ - value, - label, - sublabel, - isMonetary = false, - isPercentage = false, - decimalPlaces = 0, -}) => ( - -
- {isMonetary - ? formatCurrency(value, decimalPlaces) - : isPercentage - ? formatPercent(value, decimalPlaces) - : formatNumber(value, decimalPlaces)} -
- {label && ( -
- {label} +const MetricCell = ({ value, label, sublabel, isMonetary = false, isPercentage = false, decimalPlaces = 0 }) => { + const formattedValue = isMonetary + ? formatCurrency(value, decimalPlaces) + : isPercentage + ? formatPercent(value, decimalPlaces) + : formatNumber(value, decimalPlaces); + + return ( + +
+ {formattedValue}
- )} - {sublabel && ( -
- {sublabel} -
- )} - -); + {(label || sublabel) && ( +
+ {label || sublabel} +
+ )} + + ); +}; const getActionValue = (campaign, actionType) => { if (actionType === "impressions" || actionType === "reach") { @@ -256,55 +248,57 @@ const SkeletonMetricCard = () => (
- +
- +
- +
); const SkeletonTable = () => ( -
-
- - - - + ))} + +
- +
+ + + + + {[...Array(8)].map((_, i) => ( + - {[...Array(8)].map((_, i) => ( - - ))} - - - - {[...Array(5)].map((_, rowIndex) => ( - - + + + {[...Array(5)].map((_, rowIndex) => ( + + + {[...Array(8)].map((_, colIndex) => ( + - {[...Array(8)].map((_, colIndex) => ( - - ))} - - ))} - -
+ + + - -
+ ))} +
+
+
- - + + + +
+
+
+
+ +
-
- - -
-
-
+ ))} +
); @@ -449,7 +443,7 @@ const MetaCampaigns = () => { if (loading) { return ( - +
@@ -479,16 +473,18 @@ const MetaCampaigns = () => { if (error) { return ( - + -
{error}
+
+ {error} +
); } return ( - +
@@ -577,164 +573,162 @@ const MetaCampaigns = () => {
- -
-
- - - - - - - - - - - - - - - - {sortedCampaigns.map((campaign) => ( - - + +
- - - - - - - - - - - - - - - - - -
-
- -
-
- {campaign.objective} -
-
+ + + + + + + + + + + + + + + {sortedCampaigns.map((campaign) => ( + + - + - + - + - + - + - + - + - - - ))} - -
+ + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ {campaign.objective} +
+
+
-
-
+ + + ))} + +
); diff --git a/dashboard/src/components/dashboard/ProductGrid.jsx b/dashboard/src/components/dashboard/ProductGrid.jsx index 2ebcbcf..c282b5e 100644 --- a/dashboard/src/components/dashboard/ProductGrid.jsx +++ b/dashboard/src/components/dashboard/ProductGrid.jsx @@ -106,18 +106,18 @@ const ProductGrid = ({
- - + +
- + - + - + ); @@ -128,41 +128,41 @@ const ProductGrid = ({ - - - - @@ -185,17 +185,17 @@ const ProductGrid = ({
- + {description && ( - + )}
- - + +
@@ -218,7 +218,7 @@ const ProductGrid = ({
{title} {description && ( - {description} + {description} )}
@@ -280,7 +280,7 @@ const ProductGrid = ({
{error ? ( - + Error @@ -290,7 +290,7 @@ const ProductGrid = ({ ) : !products?.length ? (
-

No product data available

+

No product data available

Try selecting a different time range

) : ( @@ -299,8 +299,8 @@ const ProductGrid = ({
- + + + + +
- - - -
- + + + + + + {product.totalQuantity} diff --git a/dashboard/src/components/dashboard/RealtimeAnalytics.jsx b/dashboard/src/components/dashboard/RealtimeAnalytics.jsx index c596257..ab37aad 100644 --- a/dashboard/src/components/dashboard/RealtimeAnalytics.jsx +++ b/dashboard/src/components/dashboard/RealtimeAnalytics.jsx @@ -181,7 +181,7 @@ const QuotaInfo = ({ tokenQuota }) => { }; const SkeletonSummaryCard = () => ( - + @@ -247,10 +247,10 @@ const SkeletonTable = () => ( {[...Array(8)].map((_, i) => ( - + - + @@ -438,14 +438,14 @@ export const RealtimeAnalytics = () => {
- + Real-Time Analytics
-
+
@@ -453,7 +453,7 @@ export const RealtimeAnalytics = () => {
{[...Array(3)].map((_, i) => ( - + ))}
diff --git a/dashboard/src/components/dashboard/SalesChart.jsx b/dashboard/src/components/dashboard/SalesChart.jsx index 6e0f993..1b046e9 100644 --- a/dashboard/src/components/dashboard/SalesChart.jsx +++ b/dashboard/src/components/dashboard/SalesChart.jsx @@ -502,7 +502,7 @@ SummaryStats.displayName = "SummaryStats"; // Add these skeleton components near the top of the file const SkeletonChart = () => ( -
+
{/* Grid lines */} @@ -516,13 +516,13 @@ const SkeletonChart = () => ( {/* Y-axis labels */}
{[...Array(6)].map((_, i) => ( - + ))}
{/* X-axis labels */}
{[...Array(7)].map((_, i) => ( - + ))}
{/* Chart line */} @@ -540,16 +540,16 @@ const SkeletonChart = () => ( ); const SkeletonStats = () => ( -
+
{[...Array(4)].map((_, i) => ( - + - - + + - - + + ))} @@ -557,49 +557,15 @@ const SkeletonStats = () => ( ); const SkeletonTable = () => ( -
- - - - - - - - - - - - - - - - - - - - - - {[...Array(10)].map((_, i) => ( - - - - - - - - - - - - - - - - - - ))} - -
+
+
+ {[...Array(7)].map((_, i) => ( +
+ + +
+ ))} +
); @@ -724,9 +690,9 @@ const SalesChart = ({ Details - + - Daily Details + Daily Details