Standardize alert messages and clean up headers
This commit is contained in:
@@ -48,6 +48,7 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
|
||||
const METRIC_IDS = {
|
||||
PLACED_ORDER: "Y8cqcF",
|
||||
@@ -1387,16 +1388,17 @@ const EventFeed = ({
|
||||
|
||||
return (
|
||||
<Card className="flex flex-col h-full bg-white dark:bg-gray-900/60 backdrop-blur-sm">
|
||||
<CardHeader className="p-6 pb-0">
|
||||
<CardHeader className="p-6">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<CardTitle className="text-xl font-semibold text-gray-900 dark:text-gray-100">{title}</CardTitle>
|
||||
{lastUpdate && (
|
||||
<CardDescription>
|
||||
Last updated: {format(lastUpdate, "hh:mm a")}
|
||||
<CardDescription className="text-xs">
|
||||
Last updated {format(lastUpdate, "h:mm a")}
|
||||
</CardDescription>
|
||||
)}
|
||||
</div>
|
||||
{!error && (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
@@ -1506,10 +1508,12 @@ const EventFeed = ({
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Order Property Filters */}
|
||||
<div className="flex flex-wrap gap-2 justify-center mt-4">
|
||||
{/* Order Property Filters - only show if not in error state */}
|
||||
{!error && (
|
||||
<div className="flex flex-wrap gap-2 justify-center mt-4 pt-1">
|
||||
{counts.orderProperties.hasPreorder > 0 && (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
@@ -1615,28 +1619,21 @@ const EventFeed = ({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="p-6 pt-4 flex-1 overflow-hidden">
|
||||
<CardContent className="p-6 pt-0 flex-1 overflow-hidden -mt-2">
|
||||
<ScrollArea className="h-full">
|
||||
{loading && !events.length ? (
|
||||
<LoadingState />
|
||||
) : error ? (
|
||||
<div className="flex flex-col items-center justify-center p-6 text-center">
|
||||
<AlertCircle className="w-12 h-12 text-red-500 mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">
|
||||
Error Loading Feed
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{error}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => fetchEvents()}
|
||||
className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
|
||||
>
|
||||
Try Again
|
||||
</button>
|
||||
</div>
|
||||
<Alert variant="destructive" className="mt-1" >
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
Failed to load event feed: {error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : !filteredEvents || filteredEvents.length === 0 ? (
|
||||
<div className="h-full flex flex-col items-center justify-center py-16 px-4">
|
||||
<div className="bg-gray-100 dark:bg-gray-800 rounded-full p-3 mb-4">
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
|
||||
const ProductGrid = ({
|
||||
timeRange = "today",
|
||||
@@ -161,7 +162,7 @@ const ProductGrid = ({
|
||||
|
||||
return (
|
||||
<Card className="flex flex-col h-full bg-white dark:bg-gray-900/60 backdrop-blur-sm">
|
||||
<CardHeader className="p-6">
|
||||
<CardHeader className="p-6 pb-4">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<CardTitle className="text-xl font-semibold text-gray-900 dark:text-gray-100">{title}</CardTitle>
|
||||
@@ -170,6 +171,7 @@ const ProductGrid = ({
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{!error && (
|
||||
<div className="relative hidden sm:block">
|
||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
@@ -179,6 +181,7 @@ const ProductGrid = ({
|
||||
className="pl-8 h-9 w-[200px]"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Select
|
||||
value={selectedTimeRange}
|
||||
onValueChange={handleTimeRangeChange}
|
||||
@@ -203,11 +206,13 @@ const ProductGrid = ({
|
||||
{loading ? (
|
||||
<LoadingState />
|
||||
) : error ? (
|
||||
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||
<AlertCircle className="h-12 w-12 text-destructive mb-4" />
|
||||
<p className="font-medium mb-2">Error loading products</p>
|
||||
<p className="text-sm text-muted-foreground">{error}</p>
|
||||
</div>
|
||||
<Alert variant="destructive" >
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
Failed to load products: {error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : !products?.length ? (
|
||||
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||
<Package className="h-12 w-12 text-muted-foreground mb-4" />
|
||||
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
|
||||
const METRIC_IDS = {
|
||||
PLACED_ORDER: "Y8cqcF",
|
||||
@@ -675,7 +676,7 @@ const SalesChart = ({
|
||||
|
||||
return (
|
||||
<Card className="w-full bg-white dark:bg-gray-900/60 backdrop-blur-sm">
|
||||
<CardHeader className="p-6">
|
||||
<CardHeader className="p-6 pb-4">
|
||||
<div className="flex flex-col space-y-2">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
@@ -684,6 +685,7 @@ const SalesChart = ({
|
||||
</CardTitle>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{!error && (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" className="h-9">
|
||||
@@ -849,6 +851,7 @@ const SalesChart = ({
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
<Select
|
||||
value={selectedTimeRange}
|
||||
onValueChange={handleTimeRangeChange}
|
||||
@@ -867,10 +870,11 @@ const SalesChart = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Show either skeletons or actual stats */}
|
||||
{loading ? <SkeletonStats /> : <SummaryStats stats={summaryStats} />}
|
||||
{/* Show stats only if not in error state */}
|
||||
{!error && (loading ? <SkeletonStats /> : <SummaryStats stats={summaryStats} />)}
|
||||
|
||||
{/* Metric Toggles */}
|
||||
{/* Show metric toggles only if not in error state */}
|
||||
{!error && (
|
||||
<div className="flex items-center gap-2 pt-2">
|
||||
<div className="flex flex-wrap gap-1">
|
||||
<Button
|
||||
@@ -938,6 +942,7 @@ const SalesChart = ({
|
||||
Compare Prev Period
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
@@ -951,13 +956,13 @@ const SalesChart = ({
|
||||
{showDailyTable && <SkeletonTable />}
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex items-center justify-center h-[400px] text-destructive">
|
||||
<div className="text-center">
|
||||
<AlertCircle className="h-12 w-12 mx-auto mb-4" />
|
||||
<div className="font-medium mb-2">Error loading sales data</div>
|
||||
<div className="text-sm text-muted-foreground">{error}</div>
|
||||
</div>
|
||||
</div>
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
Failed to load sales data: {error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : !data.length ? (
|
||||
<div className="flex items-center justify-center h-[400px] text-muted-foreground">
|
||||
<div className="text-center">
|
||||
|
||||
@@ -67,6 +67,8 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
const formatCurrency = (value, minimumFractionDigits = 0) => {
|
||||
if (!value || isNaN(value)) return "$0";
|
||||
@@ -1401,21 +1403,13 @@ const StatCards = ({
|
||||
|
||||
if (!cachedData && error) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center p-6 text-center">
|
||||
<AlertCircle className="w-12 h-12 text-red-500 mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">
|
||||
Error Loading Data
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{error}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => fetchDetailData(metric)}
|
||||
className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
|
||||
>
|
||||
Try Again
|
||||
</button>
|
||||
</div>
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
Failed to load stats: {error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1519,8 +1513,8 @@ const StatCards = ({
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Card className="w-full bg-white dark:bg-gray-900/60 backdrop-blur-sm">
|
||||
<CardHeader className="p-6">
|
||||
<Card className="w-full bg-white dark:bg-gray-900/60 backdrop-blur-sm h-full">
|
||||
<CardHeader className="p-6 pb-4">
|
||||
<div className="flex flex-col space-y-2">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
@@ -1549,14 +1543,16 @@ const StatCards = ({
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Rest of the header content */}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-6 pt-0">
|
||||
<p className="text-destructive text-center py-8">
|
||||
Error loading stats: {error}
|
||||
</p>
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
Failed to load stats: {error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -1576,16 +1572,12 @@ const StatCards = ({
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<CardTitle className="text-xl font-semibold text-gray-900 dark:text-gray-100">{title}</CardTitle>
|
||||
{description && (
|
||||
<CardDescription className="mt-1">{description}</CardDescription>
|
||||
{lastUpdate && !loading && (
|
||||
<CardDescription className="text-xs"> Last updated {lastUpdate.toFormat("h:mm a")}</CardDescription>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{lastUpdate && !loading && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Last updated: {lastUpdate.toFormat("hh:mm a")}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<Select value={timeRange} onValueChange={setTimeRange}>
|
||||
<SelectTrigger className="w-[130px] h-9">
|
||||
<SelectValue placeholder="Select time range" />
|
||||
@@ -1600,8 +1592,6 @@ const StatCards = ({
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Rest of the header content */}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-6 pt-0">
|
||||
|
||||
Reference in New Issue
Block a user