@pattern-stack/frontend-patterns 0.0.6 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atoms/composed/index.d.ts +0 -1
- package/dist/atoms/composed/index.d.ts.map +1 -1
- package/dist/atoms/types/index.d.ts +0 -2
- package/dist/atoms/types/index.d.ts.map +1 -1
- package/dist/atoms/ui/ErrorBoundary.d.ts +1 -1
- package/dist/atoms/ui/button.d.ts +1 -1
- package/dist/atoms/utils/utils.d.ts +0 -2
- package/dist/atoms/utils/utils.d.ts.map +1 -1
- package/dist/features/auth/components/ProtectedRoute.d.ts +1 -1
- package/dist/frontend-patterns.css +1 -1
- package/dist/index.es.js +15 -403
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +14 -403
- package/dist/index.js.map +1 -1
- package/dist/molecules/layout/Sidebar.d.ts.map +1 -1
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +0 -2
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +1 -1
- package/dist/molecules/layout/index.d.ts +0 -3
- package/dist/molecules/layout/index.d.ts.map +1 -1
- package/dist/templates/factory.d.ts +1 -2
- package/dist/templates/factory.d.ts.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/package.json +3 -7
- package/src/App.tsx +1 -11
- package/src/atoms/composed/index.ts +0 -1
- package/src/atoms/types/index.ts +1 -3
- package/src/atoms/utils/utils.ts +2 -4
- package/src/molecules/layout/Sidebar.tsx +23 -10
- package/src/molecules/layout/SidebarButton/SidebarButton.tsx +10 -32
- package/src/molecules/layout/index.ts +1 -4
- package/src/organisms/index.ts +1 -5
- package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +75 -77
- package/src/pages/AdminShowcase/index.tsx +1 -2
- package/src/pages/index.ts +1 -2
- package/src/templates/factory.tsx +7 -14
- package/src/templates/index.ts +0 -4
- package/dist/atoms/composed/SalesPanel/SalesPanel.d.ts +0 -19
- package/dist/atoms/composed/SalesPanel/SalesPanel.d.ts.map +0 -1
- package/dist/atoms/composed/SalesPanel/index.d.ts +0 -2
- package/dist/atoms/composed/SalesPanel/index.d.ts.map +0 -1
- package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts +0 -63
- package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts.map +0 -1
- package/dist/atoms/types/entity-config.d.ts +0 -117
- package/dist/atoms/types/entity-config.d.ts.map +0 -1
- package/dist/atoms/types/navigation.d.ts +0 -30
- package/dist/atoms/types/navigation.d.ts.map +0 -1
- package/dist/atoms/utils/icon-resolver.d.ts +0 -72
- package/dist/atoms/utils/icon-resolver.d.ts.map +0 -1
- package/dist/atoms/utils/metric-engine.d.ts +0 -30
- package/dist/atoms/utils/metric-engine.d.ts.map +0 -1
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts +0 -16
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts.map +0 -1
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts +0 -2
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts.map +0 -1
- package/dist/molecules/layout/NavigationContext.d.ts +0 -15
- package/dist/molecules/layout/NavigationContext.d.ts.map +0 -1
- package/src/__tests__/atoms/composed/databadge.test.tsx +0 -106
- package/src/__tests__/atoms/composed/statcard.test.tsx +0 -133
- package/src/__tests__/atoms/utils/icon-resolver.test.tsx +0 -140
- package/src/atoms/composed/SalesPanel/SalesPanel.tsx +0 -116
- package/src/atoms/composed/SalesPanel/index.ts +0 -1
- package/src/atoms/composed/SalesPanel/mockSalesData.ts +0 -151
- package/src/atoms/types/entity-config.ts +0 -127
- package/src/atoms/types/navigation.ts +0 -43
- package/src/atoms/utils/icon-resolver.tsx +0 -54
- package/src/atoms/utils/metric-engine.ts +0 -236
- package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +0 -42
- package/src/molecules/layout/DashboardWithSidePanel/index.ts +0 -1
- package/src/molecules/layout/NavigationContext.tsx +0 -63
- package/src/organisms/entity/CategoryBreakdownPanel.tsx +0 -427
- package/src/organisms/entity/EntityListPanel.tsx +0 -339
- package/src/organisms/entity/MetricsOverviewPanel.tsx +0 -236
- package/src/organisms/entity/TrendAnalysisPanel.tsx +0 -337
- package/src/organisms/entity/index.ts +0 -4
- package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +0 -158
- package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +0 -137
- package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +0 -117
- package/src/pages/EntityShowcase/index.ts +0 -2
- package/src/pages/EntityTemplateExample.tsx +0 -229
- package/src/pages/TestEntityTemplate.tsx +0 -40
- package/src/templates/entity/EntityManagementTemplate.tsx +0 -430
- package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +0 -277
- package/src/templates/entity/configs/financial-config.ts +0 -141
- package/src/templates/entity/configs/index.ts +0 -1
- package/src/templates/entity/index.ts +0 -3
- package/src/templates/financial/FinancialDashboardTemplate.tsx +0 -326
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './style.css';
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -6,18 +6,19 @@ import { clsx } from "clsx";
|
|
|
6
6
|
import { twMerge } from "tailwind-merge";
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
import React__default, { useRef, useState, useEffect, Component, createContext, useContext, useMemo, useId, useCallback } from "react";
|
|
9
|
-
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
10
|
-
import { Menu, HelpCircle, Info, AlertCircle, Check, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, ChevronUp, ChevronLeft, ChevronDown, ChevronRight, Music, Video, Image, Folder, File, Flag, Tag, Bookmark, Heart, Star, MapPin, Clock, Calendar, Phone, Mail, Unlock, Lock, Share, Upload, Download, Eye, Trash2, Edit, Plus, Search, Bell, Settings, Home, Layout, TrendingUp, Database, BarChart3, Users, Shield, X, Palette, Circle, Loader2, Target, ExternalLink, TrendingDown, Minus, FileX, Sparkles, User, Sun, Moon, UserCircle, LogOut, ChevronsUpDown, AreaChart, LineChart, CheckCircle, AlertTriangle, Square, Waves, Zap, TreePine, Sunset, Building2, DollarSign, ShoppingCart, MoreHorizontal, Filter, Activity, RefreshCw, FileText, History, Save, Copy, Grid3X3, Layers, XCircle } from "lucide-react";
|
|
11
9
|
import { cva } from "class-variance-authority";
|
|
12
10
|
import axios from "axios";
|
|
13
11
|
import { useQuery, useQueryClient, useMutation, QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
12
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
14
13
|
import { Slot } from "@radix-ui/react-slot";
|
|
15
14
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
16
15
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
17
16
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
17
|
+
import { ChevronRight, Check, Circle, Loader2, ArrowRight, TrendingUp, TrendingDown, Minus, FileX, AlertCircle, Search, Database, Sparkles, Mail, Lock, Shield, User, Sun, Moon, UserCircle, Settings, LogOut, X, ChevronsUpDown, ChevronUp, ChevronDown, ChevronLeft, Clock, Calendar, BarChart3, AreaChart, LineChart, Upload, Image, File, CheckCircle, Info, AlertTriangle, Home, Palette, Square, Waves, Zap, TreePine, Sunset, Building2, Users, DollarSign, ShoppingCart, Menu, MoreHorizontal, Plus, Filter, Download, Activity, RefreshCw, Eye, Edit, Trash2, FileText, History, ArrowLeft, Save, Copy, ExternalLink, Grid3X3, Layers, XCircle } from "lucide-react";
|
|
18
18
|
import { createPortal } from "react-dom";
|
|
19
19
|
import { useLocation, useNavigate, useSearchParams, Outlet, BrowserRouter, Routes, Route } from "react-router-dom";
|
|
20
20
|
import { createRoot } from "react-dom/client";
|
|
21
|
+
import "@tanstack/react-query-devtools";
|
|
21
22
|
const APP_NAME = "Design System Showcase";
|
|
22
23
|
const API_ENDPOINTS = {
|
|
23
24
|
HEALTH: "/health"
|
|
@@ -243,240 +244,6 @@ const tooltipContent = {
|
|
|
243
244
|
profile: "Profile",
|
|
244
245
|
account: "Account settings"
|
|
245
246
|
};
|
|
246
|
-
class MetricCalculationEngine {
|
|
247
|
-
static calculateMetric(config, data, previousData) {
|
|
248
|
-
const currentValue = this.aggregateValue(config, data);
|
|
249
|
-
const previousValue = previousData ? this.aggregateValue(config, previousData) : void 0;
|
|
250
|
-
const trend = this.calculateTrend(currentValue, previousValue);
|
|
251
|
-
const formattedValue = this.formatValue(currentValue, config.format, config.type);
|
|
252
|
-
const target = typeof config.target === "function" ? config.target(data) : config.target;
|
|
253
|
-
return {
|
|
254
|
-
current: currentValue,
|
|
255
|
-
previous: previousValue,
|
|
256
|
-
trend,
|
|
257
|
-
target,
|
|
258
|
-
formattedValue
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
static aggregateValue(config, data) {
|
|
262
|
-
if (!data.length) return 0;
|
|
263
|
-
const values = data.map((item) => {
|
|
264
|
-
const value = this.extractValue(item, config.key);
|
|
265
|
-
return typeof value === "number" ? value : 0;
|
|
266
|
-
}).filter((value) => !isNaN(value));
|
|
267
|
-
if (!values.length) return 0;
|
|
268
|
-
switch (config.aggregation || "sum") {
|
|
269
|
-
case "sum":
|
|
270
|
-
return values.reduce((sum, value) => sum + value, 0);
|
|
271
|
-
case "avg":
|
|
272
|
-
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
273
|
-
case "count":
|
|
274
|
-
return values.length;
|
|
275
|
-
case "min":
|
|
276
|
-
return Math.min(...values);
|
|
277
|
-
case "max":
|
|
278
|
-
return Math.max(...values);
|
|
279
|
-
default:
|
|
280
|
-
return values.reduce((sum, value) => sum + value, 0);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
static extractValue(item, key) {
|
|
284
|
-
return key.split(".").reduce((obj, k) => obj == null ? void 0 : obj[k], item);
|
|
285
|
-
}
|
|
286
|
-
static calculateTrend(current, previous) {
|
|
287
|
-
if (previous === void 0 || previous === 0) return "neutral";
|
|
288
|
-
const change = (current - previous) / Math.abs(previous) * 100;
|
|
289
|
-
if (change > 1) return "up";
|
|
290
|
-
if (change < -1) return "down";
|
|
291
|
-
return "neutral";
|
|
292
|
-
}
|
|
293
|
-
static formatValue(value, format, type) {
|
|
294
|
-
let formatted = value;
|
|
295
|
-
if ((format == null ? void 0 : format.decimals) !== void 0) {
|
|
296
|
-
formatted = Number(value.toFixed(format.decimals));
|
|
297
|
-
}
|
|
298
|
-
let result = formatted.toString();
|
|
299
|
-
if ((format == null ? void 0 : format.thousands) !== false && Math.abs(formatted) >= 1e3) {
|
|
300
|
-
result = formatted.toLocaleString();
|
|
301
|
-
}
|
|
302
|
-
switch (type) {
|
|
303
|
-
case "currency":
|
|
304
|
-
result = new Intl.NumberFormat("en-US", {
|
|
305
|
-
style: "currency",
|
|
306
|
-
currency: "USD",
|
|
307
|
-
minimumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2,
|
|
308
|
-
maximumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2
|
|
309
|
-
}).format(formatted);
|
|
310
|
-
break;
|
|
311
|
-
case "percentage":
|
|
312
|
-
result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 1)}%`;
|
|
313
|
-
break;
|
|
314
|
-
case "duration":
|
|
315
|
-
result = this.formatDuration(formatted);
|
|
316
|
-
break;
|
|
317
|
-
case "ratio":
|
|
318
|
-
result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 2)}:1`;
|
|
319
|
-
break;
|
|
320
|
-
default:
|
|
321
|
-
if (format == null ? void 0 : format.prefix) result = format.prefix + result;
|
|
322
|
-
if (format == null ? void 0 : format.suffix) result = result + format.suffix;
|
|
323
|
-
}
|
|
324
|
-
return result;
|
|
325
|
-
}
|
|
326
|
-
static formatDuration(minutes) {
|
|
327
|
-
const hours = Math.floor(minutes / 60);
|
|
328
|
-
const mins = Math.floor(minutes % 60);
|
|
329
|
-
if (hours > 0) {
|
|
330
|
-
return `${hours}h ${mins}m`;
|
|
331
|
-
}
|
|
332
|
-
return `${mins}m`;
|
|
333
|
-
}
|
|
334
|
-
static calculateTrendData(config, data, dateField = "date", periods = 12) {
|
|
335
|
-
const groupedData = this.groupByPeriod(data, dateField);
|
|
336
|
-
const sortedDates = Object.keys(groupedData).sort();
|
|
337
|
-
return sortedDates.slice(-periods).map((date) => ({
|
|
338
|
-
date,
|
|
339
|
-
value: this.aggregateValue(config, groupedData[date]),
|
|
340
|
-
label: this.formatDateLabel(date)
|
|
341
|
-
}));
|
|
342
|
-
}
|
|
343
|
-
static groupByPeriod(data, dateField) {
|
|
344
|
-
return data.reduce((groups, item) => {
|
|
345
|
-
const date = this.extractValue(item, dateField);
|
|
346
|
-
if (!date) return groups;
|
|
347
|
-
const period = new Date(date).toISOString().split("T")[0];
|
|
348
|
-
if (!groups[period]) groups[period] = [];
|
|
349
|
-
groups[period].push(item);
|
|
350
|
-
return groups;
|
|
351
|
-
}, {});
|
|
352
|
-
}
|
|
353
|
-
static formatDateLabel(dateString) {
|
|
354
|
-
const date = new Date(dateString);
|
|
355
|
-
return date.toLocaleDateString("en-US", {
|
|
356
|
-
month: "short",
|
|
357
|
-
day: "numeric"
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
static calculateCategoryBreakdown(data, categoryField, valueField, maxCategories = 8) {
|
|
361
|
-
const groups = data.reduce((acc, item) => {
|
|
362
|
-
const category = String(this.extractValue(item, categoryField) || "Unknown");
|
|
363
|
-
const value = this.extractValue(item, valueField) || 0;
|
|
364
|
-
if (!acc[category]) acc[category] = 0;
|
|
365
|
-
acc[category] += typeof value === "number" ? value : 0;
|
|
366
|
-
return acc;
|
|
367
|
-
}, {});
|
|
368
|
-
const total = Object.values(groups).reduce((sum, value) => sum + value, 0);
|
|
369
|
-
let categories = Object.entries(groups).map(([category, value]) => ({
|
|
370
|
-
category,
|
|
371
|
-
value,
|
|
372
|
-
percentage: total > 0 ? value / total * 100 : 0
|
|
373
|
-
})).sort((a, b) => b.value - a.value);
|
|
374
|
-
if (categories.length > maxCategories) {
|
|
375
|
-
const topCategories = categories.slice(0, maxCategories - 1);
|
|
376
|
-
const otherValue = categories.slice(maxCategories - 1).reduce((sum, cat) => sum + cat.value, 0);
|
|
377
|
-
topCategories.push({
|
|
378
|
-
category: "Other",
|
|
379
|
-
value: otherValue,
|
|
380
|
-
percentage: total > 0 ? otherValue / total * 100 : 0
|
|
381
|
-
});
|
|
382
|
-
categories = topCategories;
|
|
383
|
-
}
|
|
384
|
-
return categories;
|
|
385
|
-
}
|
|
386
|
-
static detectInsights(metrics, thresholds = {}) {
|
|
387
|
-
const insights = [];
|
|
388
|
-
for (const [key, metric] of Object.entries(metrics)) {
|
|
389
|
-
const threshold = thresholds[key];
|
|
390
|
-
if (metric.target && metric.current < metric.target * 0.8) {
|
|
391
|
-
insights.push({
|
|
392
|
-
type: "negative",
|
|
393
|
-
message: `${key} is significantly below target`,
|
|
394
|
-
value: metric.current
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
if (metric.trend === "up" && metric.previous && metric.current > metric.previous * 1.2) {
|
|
398
|
-
insights.push({
|
|
399
|
-
type: "positive",
|
|
400
|
-
message: `${key} showing strong growth`,
|
|
401
|
-
value: metric.current
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
if (threshold && metric.current >= threshold.critical) {
|
|
405
|
-
insights.push({
|
|
406
|
-
type: "negative",
|
|
407
|
-
message: `${key} has reached critical threshold`,
|
|
408
|
-
value: metric.current
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return insights.slice(0, 5);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
const iconMap = {
|
|
416
|
-
Palette,
|
|
417
|
-
Menu,
|
|
418
|
-
X,
|
|
419
|
-
Shield,
|
|
420
|
-
Users,
|
|
421
|
-
BarChart3,
|
|
422
|
-
Database,
|
|
423
|
-
TrendingUp,
|
|
424
|
-
Layout,
|
|
425
|
-
Home,
|
|
426
|
-
Settings,
|
|
427
|
-
Bell,
|
|
428
|
-
Search,
|
|
429
|
-
Plus,
|
|
430
|
-
Edit,
|
|
431
|
-
Trash2,
|
|
432
|
-
Eye,
|
|
433
|
-
Download,
|
|
434
|
-
Upload,
|
|
435
|
-
Share,
|
|
436
|
-
Lock,
|
|
437
|
-
Unlock,
|
|
438
|
-
Mail,
|
|
439
|
-
Phone,
|
|
440
|
-
Calendar,
|
|
441
|
-
Clock,
|
|
442
|
-
MapPin,
|
|
443
|
-
Star,
|
|
444
|
-
Heart,
|
|
445
|
-
Bookmark,
|
|
446
|
-
Tag,
|
|
447
|
-
Flag,
|
|
448
|
-
File,
|
|
449
|
-
Folder,
|
|
450
|
-
Image,
|
|
451
|
-
Video,
|
|
452
|
-
Music,
|
|
453
|
-
ChevronRight,
|
|
454
|
-
ChevronDown,
|
|
455
|
-
ChevronLeft,
|
|
456
|
-
ChevronUp,
|
|
457
|
-
ArrowRight,
|
|
458
|
-
ArrowLeft,
|
|
459
|
-
ArrowUp,
|
|
460
|
-
ArrowDown,
|
|
461
|
-
Check,
|
|
462
|
-
AlertCircle,
|
|
463
|
-
Info,
|
|
464
|
-
HelpCircle
|
|
465
|
-
};
|
|
466
|
-
const Icon = ({ name, className = "w-5 h-5", size, ...props }) => {
|
|
467
|
-
const IconComponent = iconMap[name];
|
|
468
|
-
if (!IconComponent) {
|
|
469
|
-
console.warn(`Icon "${name}" not found. Using default Menu icon.`);
|
|
470
|
-
return /* @__PURE__ */ jsx(Menu, { className, size, ...props });
|
|
471
|
-
}
|
|
472
|
-
return /* @__PURE__ */ jsx(IconComponent, { className, size, ...props });
|
|
473
|
-
};
|
|
474
|
-
const getIcon = (name) => {
|
|
475
|
-
return iconMap[name] || Menu;
|
|
476
|
-
};
|
|
477
|
-
const isValidIcon = (name) => {
|
|
478
|
-
return name in iconMap;
|
|
479
|
-
};
|
|
480
247
|
function cn(...inputs) {
|
|
481
248
|
return twMerge(clsx(inputs));
|
|
482
249
|
}
|
|
@@ -1498,83 +1265,6 @@ const DataBadge = ({
|
|
|
1498
1265
|
}
|
|
1499
1266
|
return badge;
|
|
1500
1267
|
};
|
|
1501
|
-
const getStageStatus = (stage) => {
|
|
1502
|
-
switch (stage) {
|
|
1503
|
-
case "Closed Won":
|
|
1504
|
-
return "success";
|
|
1505
|
-
case "Negotiation":
|
|
1506
|
-
return "warning";
|
|
1507
|
-
case "Proposal Sent":
|
|
1508
|
-
return "info";
|
|
1509
|
-
case "Qualified":
|
|
1510
|
-
return "info";
|
|
1511
|
-
case "Discovery":
|
|
1512
|
-
return "neutral";
|
|
1513
|
-
default:
|
|
1514
|
-
return "neutral";
|
|
1515
|
-
}
|
|
1516
|
-
};
|
|
1517
|
-
const SalesPanel = ({
|
|
1518
|
-
sales,
|
|
1519
|
-
onSaleClick,
|
|
1520
|
-
onClose
|
|
1521
|
-
}) => {
|
|
1522
|
-
const topDeals = sales.slice(0, 5);
|
|
1523
|
-
const totalValue = sales.reduce((sum, sale) => sum + sale.amount, 0);
|
|
1524
|
-
return /* @__PURE__ */ jsxs("div", { className: "fixed right-0 top-16 h-[calc(100vh-4rem)] w-72 bg-background border-l border-border shadow-lg flex flex-col z-30", children: [
|
|
1525
|
-
/* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1526
|
-
/* @__PURE__ */ jsxs("h3", { className: "font-medium flex items-center gap-2", children: [
|
|
1527
|
-
/* @__PURE__ */ jsx(Target, { className: "w-4 h-4" }),
|
|
1528
|
-
"Pipeline"
|
|
1529
|
-
] }),
|
|
1530
|
-
onClose && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, children: "×" })
|
|
1531
|
-
] }) }),
|
|
1532
|
-
/* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1533
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
1534
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Total Value" }),
|
|
1535
|
-
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-green-600", children: [
|
|
1536
|
-
"$",
|
|
1537
|
-
totalValue.toLocaleString()
|
|
1538
|
-
] })
|
|
1539
|
-
] }),
|
|
1540
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
1541
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Active Deals" }),
|
|
1542
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: sales.length })
|
|
1543
|
-
] })
|
|
1544
|
-
] }) }),
|
|
1545
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-auto p-3", children: [
|
|
1546
|
-
/* @__PURE__ */ jsx("h4", { className: "text-sm font-medium mb-3", children: "Recent Opportunities" }),
|
|
1547
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: topDeals.map((sale) => /* @__PURE__ */ jsxs(
|
|
1548
|
-
"div",
|
|
1549
|
-
{
|
|
1550
|
-
className: "p-2 border border-border rounded-md hover:bg-muted/50 cursor-pointer transition-colors",
|
|
1551
|
-
onClick: () => onSaleClick == null ? void 0 : onSaleClick(sale),
|
|
1552
|
-
children: [
|
|
1553
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start mb-1", children: [
|
|
1554
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1555
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: sale.customer }),
|
|
1556
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground truncate", children: sale.product })
|
|
1557
|
-
] }),
|
|
1558
|
-
/* @__PURE__ */ jsx("div", { className: "text-right ml-2", children: /* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-green-600", children: [
|
|
1559
|
-
"$",
|
|
1560
|
-
sale.amount.toLocaleString()
|
|
1561
|
-
] }) })
|
|
1562
|
-
] }),
|
|
1563
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
|
|
1564
|
-
/* @__PURE__ */ jsx(DataBadge, { variant: "status", status: getStageStatus(sale.stage), children: sale.stage }),
|
|
1565
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: sale.salesperson })
|
|
1566
|
-
] })
|
|
1567
|
-
]
|
|
1568
|
-
},
|
|
1569
|
-
sale.id
|
|
1570
|
-
)) })
|
|
1571
|
-
] }),
|
|
1572
|
-
/* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "w-full", children: [
|
|
1573
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "w-4 h-4 mr-2" }),
|
|
1574
|
-
"View All Deals"
|
|
1575
|
-
] }) })
|
|
1576
|
-
] });
|
|
1577
|
-
};
|
|
1578
1268
|
const StatCard = ({
|
|
1579
1269
|
title,
|
|
1580
1270
|
value,
|
|
@@ -5839,42 +5529,6 @@ const useSidebar = () => {
|
|
|
5839
5529
|
}
|
|
5840
5530
|
return context;
|
|
5841
5531
|
};
|
|
5842
|
-
const NavigationContext = createContext(void 0);
|
|
5843
|
-
const defaultShowcaseNavigation = [
|
|
5844
|
-
{ value: "showcase", label: "Showcase", icon: "Palette", path: "/showcase", category: 5 },
|
|
5845
|
-
{ value: "admin-dashboard", label: "Admin Dashboard", icon: "Shield", path: "/admin/dashboard", category: 2 },
|
|
5846
|
-
{ value: "admin-users", label: "User Management", icon: "Users", path: "/admin/users", category: 3 },
|
|
5847
|
-
{ value: "admin-sales", label: "Sales Dashboard", icon: "TrendingUp", path: "/admin/sales", category: 4 },
|
|
5848
|
-
{ value: "entity-performance", label: "Performance Dashboard", icon: "BarChart3", path: "/entity/performance", category: 6 },
|
|
5849
|
-
{ value: "entity-management", label: "Entity Management", icon: "Database", path: "/entity/management", category: 7 },
|
|
5850
|
-
{ value: "entity-template", label: "Template Example", icon: "Layout", path: "/entity/template-example", category: 1 }
|
|
5851
|
-
];
|
|
5852
|
-
const NavigationProvider = ({ children, initialNavigation }) => {
|
|
5853
|
-
const [navigation, setNavigation] = React__default.useState(
|
|
5854
|
-
initialNavigation || {
|
|
5855
|
-
items: defaultShowcaseNavigation,
|
|
5856
|
-
showDefaultNavigation: true,
|
|
5857
|
-
defaultExpanded: true
|
|
5858
|
-
}
|
|
5859
|
-
);
|
|
5860
|
-
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: { navigation, setNavigation }, children });
|
|
5861
|
-
};
|
|
5862
|
-
const useNavigation = () => {
|
|
5863
|
-
const context = useContext(NavigationContext);
|
|
5864
|
-
if (context === void 0) {
|
|
5865
|
-
throw new Error("useNavigation must be used within a NavigationProvider");
|
|
5866
|
-
}
|
|
5867
|
-
return context;
|
|
5868
|
-
};
|
|
5869
|
-
const getNavigationItems = (config) => {
|
|
5870
|
-
if (config.items.length > 0) {
|
|
5871
|
-
return config.items;
|
|
5872
|
-
}
|
|
5873
|
-
if (config.showDefaultNavigation !== false) {
|
|
5874
|
-
return defaultShowcaseNavigation;
|
|
5875
|
-
}
|
|
5876
|
-
return [];
|
|
5877
|
-
};
|
|
5878
5532
|
const SidebarButton = ({
|
|
5879
5533
|
icon,
|
|
5880
5534
|
label,
|
|
@@ -5882,16 +5536,13 @@ const SidebarButton = ({
|
|
|
5882
5536
|
category = 1,
|
|
5883
5537
|
expanded = false,
|
|
5884
5538
|
onClick,
|
|
5885
|
-
className
|
|
5886
|
-
badge,
|
|
5887
|
-
disabled = false
|
|
5539
|
+
className
|
|
5888
5540
|
}) => {
|
|
5889
5541
|
return /* @__PURE__ */ jsxs(
|
|
5890
5542
|
Button,
|
|
5891
5543
|
{
|
|
5892
5544
|
variant: active ? "secondary" : "ghost",
|
|
5893
5545
|
onClick,
|
|
5894
|
-
disabled,
|
|
5895
5546
|
tooltip: !expanded ? label : void 0,
|
|
5896
5547
|
className: cn(
|
|
5897
5548
|
"relative w-full justify-start gap-3 h-12",
|
|
@@ -5925,19 +5576,12 @@ const SidebarButton = ({
|
|
|
5925
5576
|
"text-sm font-medium flex-1 text-left",
|
|
5926
5577
|
active ? `text-category-${category}` : "text-foreground"
|
|
5927
5578
|
), children: label }),
|
|
5928
|
-
|
|
5929
|
-
"px-2 py-0.5 text-xs font-medium rounded-full flex-shrink-0",
|
|
5930
|
-
"bg-primary/10 text-primary"
|
|
5931
|
-
), children: badge }) : active && /* @__PURE__ */ jsx("div", { className: cn(
|
|
5579
|
+
active && /* @__PURE__ */ jsx("div", { className: cn(
|
|
5932
5580
|
"w-2 h-2 rounded-full flex-shrink-0",
|
|
5933
5581
|
`bg-category-${category}`
|
|
5934
5582
|
) })
|
|
5935
5583
|
] }),
|
|
5936
|
-
!expanded &&
|
|
5937
|
-
"px-1.5 py-0.5 text-xs font-bold rounded-full",
|
|
5938
|
-
"bg-primary text-primary-foreground",
|
|
5939
|
-
"ring-2 ring-background"
|
|
5940
|
-
), children: badge }) : active && /* @__PURE__ */ jsx("div", { className: cn(
|
|
5584
|
+
!expanded && active && /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -right-1", children: /* @__PURE__ */ jsx("div", { className: cn(
|
|
5941
5585
|
"w-2.5 h-2.5 rounded-full",
|
|
5942
5586
|
`bg-category-${category}`,
|
|
5943
5587
|
"ring-2 ring-background"
|
|
@@ -5948,11 +5592,14 @@ const SidebarButton = ({
|
|
|
5948
5592
|
};
|
|
5949
5593
|
const Sidebar = ({ className }) => {
|
|
5950
5594
|
const { isExpanded, toggleSidebar } = useSidebar();
|
|
5951
|
-
const { navigation } = useNavigation();
|
|
5952
5595
|
const location = useLocation();
|
|
5953
5596
|
const navigate = useNavigate();
|
|
5954
5597
|
const [searchParams] = useSearchParams();
|
|
5955
|
-
const items =
|
|
5598
|
+
const items = [
|
|
5599
|
+
{ value: "showcase", label: "Showcase", icon: /* @__PURE__ */ jsx(Palette, { className: "w-5 h-5" }), path: "/showcase", category: 5 },
|
|
5600
|
+
{ value: "admin-dashboard", label: "Admin Dashboard", icon: /* @__PURE__ */ jsx(Shield, { className: "w-5 h-5" }), path: "/admin/dashboard", category: 2 },
|
|
5601
|
+
{ value: "admin-users", label: "User Management", icon: /* @__PURE__ */ jsx(Users, { className: "w-5 h-5" }), path: "/admin/users", category: 3 }
|
|
5602
|
+
];
|
|
5956
5603
|
const handleNavigation = (path) => {
|
|
5957
5604
|
if (path.includes("?")) {
|
|
5958
5605
|
const [basePath, query] = path.split("?");
|
|
@@ -6008,14 +5655,12 @@ const Sidebar = ({ className }) => {
|
|
|
6008
5655
|
return /* @__PURE__ */ jsx(
|
|
6009
5656
|
SidebarButton,
|
|
6010
5657
|
{
|
|
6011
|
-
icon:
|
|
5658
|
+
icon: item.icon,
|
|
6012
5659
|
label: item.label,
|
|
6013
5660
|
active: isActive,
|
|
6014
5661
|
category: item.category,
|
|
6015
5662
|
expanded: isExpanded,
|
|
6016
|
-
onClick: () => handleNavigation(item.path)
|
|
6017
|
-
badge: item.badge,
|
|
6018
|
-
disabled: item.disabled
|
|
5663
|
+
onClick: () => handleNavigation(item.path)
|
|
6019
5664
|
},
|
|
6020
5665
|
item.value
|
|
6021
5666
|
);
|
|
@@ -6081,28 +5726,6 @@ const AppLayout = () => {
|
|
|
6081
5726
|
)
|
|
6082
5727
|
] });
|
|
6083
5728
|
};
|
|
6084
|
-
const DashboardWithSidePanel = ({
|
|
6085
|
-
children,
|
|
6086
|
-
sidePanel,
|
|
6087
|
-
showSidePanel = false,
|
|
6088
|
-
sidePanelWidth = 72,
|
|
6089
|
-
className
|
|
6090
|
-
}) => {
|
|
6091
|
-
const marginClass = `pr-${sidePanelWidth}`;
|
|
6092
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative h-full", className), children: [
|
|
6093
|
-
/* @__PURE__ */ jsx(
|
|
6094
|
-
"div",
|
|
6095
|
-
{
|
|
6096
|
-
className: cn(
|
|
6097
|
-
"transition-all duration-300",
|
|
6098
|
-
showSidePanel ? marginClass : ""
|
|
6099
|
-
),
|
|
6100
|
-
children
|
|
6101
|
-
}
|
|
6102
|
-
),
|
|
6103
|
-
showSidePanel && sidePanel
|
|
6104
|
-
] });
|
|
6105
|
-
};
|
|
6106
5729
|
const SectionHeader = ({
|
|
6107
5730
|
title,
|
|
6108
5731
|
description,
|
|
@@ -8125,7 +7748,6 @@ function createReactApp(config) {
|
|
|
8125
7748
|
enableQuery = true,
|
|
8126
7749
|
enableRouting = true,
|
|
8127
7750
|
auth,
|
|
8128
|
-
navigation,
|
|
8129
7751
|
customProviders = []
|
|
8130
7752
|
} = appConfig;
|
|
8131
7753
|
const queryClient = new QueryClient({
|
|
@@ -8160,7 +7782,7 @@ function createReactApp(config) {
|
|
|
8160
7782
|
tree = /* @__PURE__ */ jsx(Provider, { children: tree }, Provider.name);
|
|
8161
7783
|
});
|
|
8162
7784
|
if (enableRouting) {
|
|
8163
|
-
tree = /* @__PURE__ */ jsx(
|
|
7785
|
+
tree = /* @__PURE__ */ jsx(SidebarProvider, { children: tree });
|
|
8164
7786
|
}
|
|
8165
7787
|
if (enableAuth) {
|
|
8166
7788
|
tree = /* @__PURE__ */ jsx(AuthProvider, { config: auth, children: tree });
|
|
@@ -10427,7 +10049,6 @@ export {
|
|
|
10427
10049
|
DashboardCard,
|
|
10428
10050
|
DashboardGrid,
|
|
10429
10051
|
DashboardTemplate,
|
|
10430
|
-
DashboardWithSidePanel,
|
|
10431
10052
|
DataBadge,
|
|
10432
10053
|
DataDetailTemplate,
|
|
10433
10054
|
DataTable,
|
|
@@ -10455,17 +10076,14 @@ export {
|
|
|
10455
10076
|
FormField,
|
|
10456
10077
|
FormGroup,
|
|
10457
10078
|
GlobalSearch,
|
|
10458
|
-
Icon,
|
|
10459
10079
|
IconBadge,
|
|
10460
10080
|
Input,
|
|
10461
10081
|
Label,
|
|
10462
10082
|
Loading,
|
|
10463
10083
|
LoginForm,
|
|
10464
10084
|
LogoutButton,
|
|
10465
|
-
MetricCalculationEngine,
|
|
10466
10085
|
Modal,
|
|
10467
10086
|
NavMenu,
|
|
10468
|
-
NavigationProvider,
|
|
10469
10087
|
PageTemplate,
|
|
10470
10088
|
Pagination,
|
|
10471
10089
|
PaletteSwitcher,
|
|
@@ -10473,7 +10091,6 @@ export {
|
|
|
10473
10091
|
ProtectedRoute,
|
|
10474
10092
|
RESPONSIVE_CHART_HEIGHTS,
|
|
10475
10093
|
ROUTES,
|
|
10476
|
-
SalesPanel,
|
|
10477
10094
|
SearchInput,
|
|
10478
10095
|
SectionHeader,
|
|
10479
10096
|
Select,
|
|
@@ -10482,7 +10099,6 @@ export {
|
|
|
10482
10099
|
SelectTrigger,
|
|
10483
10100
|
SelectValue,
|
|
10484
10101
|
ShowcaseSection,
|
|
10485
|
-
Sidebar,
|
|
10486
10102
|
SidebarButton,
|
|
10487
10103
|
SidebarProvider,
|
|
10488
10104
|
Skeleton,
|
|
@@ -10518,10 +10134,7 @@ export {
|
|
|
10518
10134
|
getAnimationClasses,
|
|
10519
10135
|
getChartHeight,
|
|
10520
10136
|
getContainerHeightClass,
|
|
10521
|
-
getIcon,
|
|
10522
|
-
getNavigationItems,
|
|
10523
10137
|
interactionVariants,
|
|
10524
|
-
isValidIcon,
|
|
10525
10138
|
legacyPatterns,
|
|
10526
10139
|
setGlobalAuthService,
|
|
10527
10140
|
tooltipContent,
|
|
@@ -10531,7 +10144,6 @@ export {
|
|
|
10531
10144
|
useCreateExample,
|
|
10532
10145
|
useDeleteExample,
|
|
10533
10146
|
useGetExample,
|
|
10534
|
-
useNavigation,
|
|
10535
10147
|
usePermissions,
|
|
10536
10148
|
useSidebar,
|
|
10537
10149
|
useTextOverflow,
|