fluxy-bot 0.4.22 → 0.4.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxy-bot",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "Self-hosted, self-evolving AI agent with its own dashboard.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,52 +1,76 @@
1
- import { ChevronDown, FileText, SlidersHorizontal } from 'lucide-react';
2
- import ConversationAnalytics from './ConversationAnalytics';
3
- import PromoCard from './PromoCard';
4
- import TodayStats from './TodayStats';
5
- import ReportCard from './ReportCard';
1
+ const starterSuggestions = [
2
+ 'Build me a CRM',
3
+ 'Create a habit tracker',
4
+ 'Make a finance dashboard',
5
+ 'Build a task manager',
6
+ ];
6
7
 
7
8
  export default function DashboardPage() {
9
+ const handleSuggestion = (text: string) => {
10
+ // Open the chat widget and pre-fill the suggestion
11
+ const panel = document.getElementById('fluxy-widget-panel');
12
+ if (panel && !panel.classList.contains('open')) {
13
+ const toggle = document.getElementById('fluxy-widget-toggle');
14
+ toggle?.click();
15
+ }
16
+ // Give the widget a moment to open, then try to fill the input
17
+ setTimeout(() => {
18
+ const input = document.querySelector<HTMLTextAreaElement>(
19
+ '#fluxy-widget-panel textarea, #fluxy-widget-panel input[type="text"]'
20
+ );
21
+ if (input) {
22
+ const nativeSetter = Object.getOwnPropertyDescriptor(
23
+ window.HTMLTextAreaElement.prototype, 'value'
24
+ )?.set || Object.getOwnPropertyDescriptor(
25
+ window.HTMLInputElement.prototype, 'value'
26
+ )?.set;
27
+ nativeSetter?.call(input, text);
28
+ input.dispatchEvent(new Event('input', { bubbles: true }));
29
+ input.focus();
30
+ }
31
+ }, 400);
32
+ };
33
+
8
34
  return (
9
- <div className="max-w-6xl mx-auto space-y-4 sm:space-y-6">
10
- {/* Title row */}
11
- <div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3">
12
- <div>
13
- <h2 className="text-2xl sm:text-3xl font-semibold">Dashboard Overview</h2>
14
- <p className="text-sm text-muted-foreground mt-1">
15
- Overview{' '}
16
- <span className="mx-1.5 text-muted-foreground/50">&gt;</span>
17
- All Systems
18
- </p>
19
- </div>
20
- <div className="flex items-center gap-2 overflow-x-auto">
21
- <button className="flex items-center gap-1.5 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-card border border-border text-xs sm:text-sm shrink-0 hover:text-foreground transition-colors">
22
- Activity
23
- <ChevronDown className="h-3.5 w-3.5" />
24
- </button>
25
- <button className="flex items-center gap-1.5 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-card border border-border text-xs sm:text-sm shrink-0 hover:text-foreground transition-colors">
26
- Export
27
- <FileText className="h-3.5 w-3.5" />
28
- </button>
29
- <button className="flex items-center gap-1.5 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-card border border-border text-xs sm:text-sm shrink-0 hover:text-foreground transition-colors">
30
- Filter
31
- <SlidersHorizontal className="h-3.5 w-3.5" />
35
+ <div className="flex flex-col items-center justify-start h-full px-4 pt-16 sm:pt-24">
36
+ {/* Welcome message */}
37
+ <h1 className="text-2xl sm:text-3xl font-bold text-center mb-2">
38
+ Hi, I'm Fluxy
39
+ </h1>
40
+ <p className="text-muted-foreground text-sm sm:text-base text-center max-w-md mb-8">
41
+ Tell me what to build and I'll create it for you, right here.
42
+ </p>
43
+
44
+ {/* Starter suggestion chips */}
45
+ <div className="flex flex-wrap items-center justify-center gap-2 sm:gap-3 max-w-lg mb-12">
46
+ {starterSuggestions.map((suggestion) => (
47
+ <button
48
+ key={suggestion}
49
+ onClick={() => handleSuggestion(suggestion)}
50
+ className="px-4 py-2 sm:px-5 sm:py-2.5 rounded-full border border-border bg-card text-sm text-muted-foreground hover:text-foreground hover:border-primary/40 hover:bg-card/80 transition-all duration-200 active:scale-[0.97]"
51
+ >
52
+ {suggestion}
32
53
  </button>
33
- </div>
54
+ ))}
34
55
  </div>
35
56
 
36
- {/* Card grid */}
37
- <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
38
- {/* Left: tall analytics card */}
39
- <ConversationAnalytics />
40
-
41
- {/* Right column */}
42
- <div className="space-y-4">
43
- <PromoCard />
44
- <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
45
- <TodayStats />
46
- <ReportCard />
47
- </div>
48
- </div>
57
+ {/* Arrow pointing to chat */}
58
+ {/* Desktop */}
59
+ <div
60
+ id="chat-arrow-desktop"
61
+ className="hidden md:flex fixed flex-col items-center pointer-events-none"
62
+ style={{ bottom: 100, right: 100 }}
63
+ >
64
+ <img src="/arrow.png" alt="" style={{ width: 120 }} />
49
65
  </div>
66
+ {/* Mobile */}
67
+ <img
68
+ id="chat-arrow-mobile"
69
+ src="/arrow.png"
70
+ alt=""
71
+ className="block md:hidden fixed pointer-events-none"
72
+ style={{ width: 90, bottom: 75, right: 60 }}
73
+ />
50
74
  </div>
51
75
  );
52
76
  }
@@ -1,22 +1,50 @@
1
+ import { useState, useEffect } from 'react';
1
2
  import type { ReactNode } from 'react';
2
3
  import Sidebar from './Sidebar';
3
- import DashboardHeader from './DashboardHeader';
4
+ import Footer from './Footer';
5
+ import MobileNav from './MobileNav';
4
6
 
5
7
  interface Props {
6
8
  children: ReactNode;
7
9
  }
8
10
 
9
11
  export default function DashboardLayout({ children }: Props) {
12
+ const [connected, setConnected] = useState(true);
13
+
14
+ useEffect(() => {
15
+ const check = () => {
16
+ fetch('/api/health', { method: 'HEAD' })
17
+ .then(() => setConnected(true))
18
+ .catch(() => setConnected(false));
19
+ };
20
+ check();
21
+ const id = setInterval(check, 15_000);
22
+ return () => clearInterval(id);
23
+ }, []);
24
+
10
25
  return (
11
- <div className="flex h-dvh flex-col overflow-x-hidden">
12
- <DashboardHeader />
26
+ <div className="flex h-dvh flex-col bg-background">
27
+ {/* Mobile header */}
28
+ <header className="flex items-center justify-between px-4 py-3 md:hidden">
29
+ <MobileNav />
30
+ <div className="flex items-center gap-2">
31
+ <img src="/fluxy.png" alt="Fluxy" className="h-6 w-auto" />
32
+ <span className="font-semibold text-base">Fluxy</span>
33
+ </div>
34
+ <div className="w-10" />
35
+ </header>
36
+
13
37
  <div className="flex flex-1 overflow-hidden">
14
38
  {/* Desktop sidebar */}
15
39
  <div className="hidden md:flex shrink-0">
16
40
  <Sidebar />
17
41
  </div>
18
- {/* Main content */}
19
- <main className="flex-1 overflow-y-auto p-4 md:p-6">{children}</main>
42
+
43
+ {/* Main content + footer */}
44
+ <div className="flex flex-1 flex-col overflow-hidden">
45
+ <main className="flex-1 overflow-y-auto">{children}</main>
46
+ <Footer connected={connected} />
47
+ </div>
20
48
  </div>
21
49
  </div>
22
50
  );
@@ -0,0 +1,16 @@
1
+ export default function Footer({ connected }: { connected: boolean }) {
2
+ return (
3
+ <footer className="flex items-center px-4 md:px-6 py-2.5 text-[11px] text-muted-foreground/60 shrink-0">
4
+ <div className="flex items-center gap-1.5">
5
+ <div
6
+ className={`h-1.5 w-1.5 rounded-full ${
7
+ connected ? 'bg-emerald-500' : 'bg-red-500'
8
+ }`}
9
+ />
10
+ <span>{connected ? 'Connected' : 'Disconnected'}</span>
11
+ <span className="mx-1.5 text-muted-foreground/30">|</span>
12
+ <span>Fluxy v0.1.0</span>
13
+ </div>
14
+ </footer>
15
+ );
16
+ }
@@ -11,20 +11,20 @@ export default function MobileNav() {
11
11
  const [open, setOpen] = useState(false);
12
12
 
13
13
  return (
14
- <div className="md:hidden">
14
+ <>
15
15
  <button
16
16
  onClick={() => setOpen(true)}
17
- className="flex items-center justify-center h-10 w-10 rounded-full bg-card border border-border text-muted-foreground hover:text-foreground transition-colors"
17
+ className="flex items-center justify-center h-10 w-10 rounded-lg text-muted-foreground hover:text-foreground transition-colors md:hidden"
18
18
  >
19
19
  <Menu className="h-5 w-5" />
20
20
  <span className="sr-only">Open navigation</span>
21
21
  </button>
22
22
  <Sheet open={open} onOpenChange={setOpen}>
23
- <SheetContent side="left" className="p-0 w-72" showCloseButton={false}>
23
+ <SheetContent side="left" className="p-0 w-64" showCloseButton={false}>
24
24
  <SheetTitle className="sr-only">Navigation</SheetTitle>
25
25
  <Sidebar />
26
26
  </SheetContent>
27
27
  </Sheet>
28
- </div>
28
+ </>
29
29
  );
30
30
  }
@@ -1,81 +1,104 @@
1
+ import { useState } from 'react';
1
2
  import {
2
- ChevronDown,
3
3
  LayoutDashboard,
4
- MessageSquare,
5
- Brain,
6
- BookOpen,
7
- ScrollText,
8
- Settings,
4
+ AppWindow,
5
+ BarChart3,
6
+ Search,
7
+ HelpCircle,
8
+ ChevronDown,
9
9
  } from 'lucide-react';
10
10
  import { cn } from '@/lib/utils';
11
11
 
12
- const navSections = [
13
- {
14
- label: 'HOME',
15
- items: [
16
- { label: 'Overview', icon: LayoutDashboard, href: '#', active: true },
17
- { label: 'Conversations', icon: MessageSquare, href: '#' },
18
- { label: 'Models', icon: Brain, href: '#' },
19
- { label: 'Knowledge', icon: BookOpen, href: '#' },
20
- ],
21
- },
22
- {
23
- label: 'SYSTEM',
24
- items: [
25
- { label: 'Logs', icon: ScrollText, href: '#' },
26
- { label: 'Settings', icon: Settings, href: '#' },
27
- ],
28
- },
29
- ];
30
-
31
12
  function getGreeting(): string {
32
13
  const hour = new Date().getHours();
33
- if (hour < 12) return 'Good\nMorning!';
34
- if (hour < 18) return 'Good\nAfternoon!';
35
- return 'Good\nEvening!';
14
+ if (hour < 12) return 'Good\nMorning';
15
+ if (hour < 18) return 'Good\nAfternoon';
16
+ return 'Good\nEvening';
36
17
  }
37
18
 
38
19
  export default function Sidebar() {
20
+ const [appsOpen, setAppsOpen] = useState(false);
21
+
39
22
  return (
40
- <aside className="flex flex-col h-full w-72 p-6 pt-8">
41
- {/* Welcome */}
23
+ <aside className="flex flex-col h-full w-64 border-r border-border/50 bg-sidebar p-5 pt-8">
24
+ {/* Logo */}
25
+ <div className="flex items-center gap-2.5 mb-8">
26
+ <img src="/fluxy.png" alt="Fluxy" className="h-7 w-auto" />
27
+ <span className="font-semibold text-lg">Fluxy</span>
28
+ </div>
29
+
30
+ {/* Greeting */}
42
31
  <div className="mb-10">
43
- <h1 className="text-5xl font-bold leading-[1.1] whitespace-pre-line">
32
+ <h1 className="text-4xl font-bold leading-[1.1] whitespace-pre-line">
44
33
  {getGreeting()}
45
34
  </h1>
46
- <p className="text-sm text-muted-foreground mt-3">
47
- Your AI assistant dashboard
48
- </p>
35
+ <h2 className="text-4xl font-bold text-primary mt-0.5">Bruno</h2>
49
36
  </div>
50
37
 
51
- {/* Navigation sections */}
52
- <nav className="flex-1 space-y-8">
53
- {navSections.map((section) => (
54
- <div key={section.label}>
55
- <span className="text-[11px] font-medium uppercase tracking-widest text-muted-foreground mb-3 block">
56
- {section.label}
57
- </span>
58
- <div className="space-y-1">
59
- {section.items.map((item) => (
60
- <a
61
- key={item.label}
62
- href={item.href}
63
- className={cn(
64
- 'flex items-center gap-3 px-4 py-2.5 rounded-full text-sm transition-colors',
65
- item.active
66
- ? 'bg-foreground text-background font-medium'
67
- : 'text-muted-foreground hover:text-foreground',
68
- )}
69
- >
70
- <item.icon className="h-4 w-4" />
71
- {item.label}
72
- {item.active && <ChevronDown className="h-4 w-4 ml-auto" />}
73
- </a>
74
- ))}
38
+ {/* Navigation */}
39
+ <nav className="flex-1 space-y-0.5">
40
+ <NavButton icon={LayoutDashboard} label="Dashboard" active />
41
+
42
+ {/* My Apps with dropdown */}
43
+ <div>
44
+ <button
45
+ onClick={() => setAppsOpen(!appsOpen)}
46
+ className="flex items-center gap-3 w-full px-3 py-2.5 rounded-lg text-sm text-muted-foreground hover:text-foreground hover:bg-sidebar-accent/50 transition-colors"
47
+ >
48
+ <AppWindow className="h-[18px] w-[18px]" />
49
+ My Apps
50
+ <ChevronDown
51
+ className={cn(
52
+ 'h-3.5 w-3.5 ml-auto transition-transform duration-200',
53
+ appsOpen && 'rotate-180',
54
+ )}
55
+ />
56
+ </button>
57
+ {appsOpen && (
58
+ <div className="ml-9 mt-0.5 space-y-0.5">
59
+ <button className="block w-full text-left px-3 py-2 rounded-lg text-sm text-muted-foreground hover:text-foreground hover:bg-sidebar-accent/50 transition-colors">
60
+ App 1
61
+ </button>
62
+ <button className="block w-full text-left px-3 py-2 rounded-lg text-sm text-muted-foreground hover:text-foreground hover:bg-sidebar-accent/50 transition-colors">
63
+ App 2
64
+ </button>
75
65
  </div>
76
- </div>
77
- ))}
66
+ )}
67
+ </div>
68
+
69
+ <NavButton icon={BarChart3} label="Reports" />
70
+ <NavButton icon={Search} label="Research" />
71
+ <NavButton icon={HelpCircle} label="What Else?" />
78
72
  </nav>
73
+
74
+ {/* Bottom info */}
75
+ <div className="pt-4 border-t border-border/50">
76
+ <p className="text-[11px] text-muted-foreground/60">Fluxy v0.1.0</p>
77
+ </div>
79
78
  </aside>
80
79
  );
81
80
  }
81
+
82
+ function NavButton({
83
+ icon: Icon,
84
+ label,
85
+ active,
86
+ }: {
87
+ icon: React.ComponentType<{ className?: string }>;
88
+ label: string;
89
+ active?: boolean;
90
+ }) {
91
+ return (
92
+ <button
93
+ className={cn(
94
+ 'flex items-center gap-3 w-full px-3 py-2.5 rounded-lg text-sm transition-colors',
95
+ active
96
+ ? 'bg-sidebar-accent text-foreground font-medium'
97
+ : 'text-muted-foreground hover:text-foreground hover:bg-sidebar-accent/50',
98
+ )}
99
+ >
100
+ <Icon className="h-[18px] w-[18px]" />
101
+ {label}
102
+ </button>
103
+ );
104
+ }
@@ -1,98 +0,0 @@
1
- import { ChevronDown, MoreHorizontal } from 'lucide-react';
2
- import { Card, CardContent } from '@/components/ui/card';
3
-
4
- const weeklyActivity = [
5
- { model: 'GPT-4o', days: [3, 2, 4, 3, 1, 2, 0] },
6
- { model: 'Claude', days: [2, 4, 3, 4, 2, 1, 1] },
7
- { model: 'Local', days: [1, 1, 2, 1, 3, 4, 2] },
8
- ];
9
-
10
- const dayLabels = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
11
-
12
- const activityColors = [
13
- '#2a2a2a', '#1e3a5f', '#2c5a8f', '#3578bf', '#3C8FFF',
14
- ];
15
-
16
- const activityLegend = [
17
- { label: '< 10', level: 1 },
18
- { label: '10–50', level: 2 },
19
- { label: '> 50', level: 3 },
20
- { label: '100+', level: 4 },
21
- { label: 'None', level: 0 },
22
- ];
23
-
24
- export default function ConversationAnalytics() {
25
- return (
26
- <Card className="bg-card border-border h-full">
27
- <CardContent className="p-4 sm:p-6">
28
- {/* Title row */}
29
- <div className="flex items-center justify-between mb-4 sm:mb-6">
30
- <h3 className="text-base sm:text-lg font-semibold">Conversation Activity</h3>
31
- <div className="flex items-center gap-2">
32
- <button className="flex items-center gap-1.5 px-3 py-1.5 rounded-full border border-border text-xs sm:text-sm">
33
- Weekly
34
- <ChevronDown className="h-3.5 w-3.5" />
35
- </button>
36
- <button className="flex items-center justify-center h-8 w-8 rounded-full border border-border text-muted-foreground">
37
- <MoreHorizontal className="h-4 w-4" />
38
- </button>
39
- </div>
40
- </div>
41
-
42
- {/* Total + legend */}
43
- <div className="flex flex-col sm:flex-row sm:items-end sm:justify-between gap-3 mb-4 sm:mb-6">
44
- <div>
45
- <span className="text-3xl sm:text-4xl font-bold">2.4K</span>
46
- <p className="text-sm text-muted-foreground mt-1">Total Messages</p>
47
- </div>
48
- <div className="flex items-center gap-2 sm:gap-3 flex-wrap">
49
- {activityLegend.map((item) => (
50
- <div key={item.label} className="flex items-center gap-1">
51
- <div
52
- className="h-2 w-2 sm:h-2.5 sm:w-2.5 rounded-full"
53
- style={{ backgroundColor: activityColors[item.level] }}
54
- />
55
- <span className="text-[10px] sm:text-xs text-muted-foreground">{item.label}</span>
56
- </div>
57
- ))}
58
- </div>
59
- </div>
60
-
61
- {/* Activity grid */}
62
- <div className="space-y-2 sm:space-y-3">
63
- {weeklyActivity.map((row) => (
64
- <div key={row.model} className="flex items-center gap-2 sm:gap-4">
65
- <span className="text-xs sm:text-sm text-muted-foreground w-12 sm:w-16 shrink-0">
66
- {row.model}
67
- </span>
68
- <div className="grid grid-cols-7 gap-1.5 sm:gap-2 flex-1">
69
- {row.days.map((level, i) => (
70
- <div
71
- key={i}
72
- className="aspect-square rounded-full max-w-10"
73
- style={{ backgroundColor: activityColors[level] }}
74
- />
75
- ))}
76
- </div>
77
- </div>
78
- ))}
79
- </div>
80
-
81
- {/* Day labels */}
82
- <div className="flex items-center gap-2 sm:gap-4 mt-2 sm:mt-4">
83
- <div className="w-12 sm:w-16 shrink-0" />
84
- <div className="grid grid-cols-7 gap-1.5 sm:gap-2 flex-1">
85
- {dayLabels.map((d, i) => (
86
- <span
87
- key={i}
88
- className="flex items-center justify-center text-[10px] sm:text-xs text-muted-foreground max-w-10 aspect-square"
89
- >
90
- {d}
91
- </span>
92
- ))}
93
- </div>
94
- </div>
95
- </CardContent>
96
- </Card>
97
- );
98
- }
@@ -1,44 +0,0 @@
1
- import { ArrowUpRight } from 'lucide-react';
2
- import { Card, CardContent } from '@/components/ui/card';
3
-
4
- export default function PromoCard() {
5
- return (
6
- <Card
7
- className="border-border overflow-hidden relative"
8
- style={{
9
- background:
10
- 'radial-gradient(ellipse at 80% 20%, rgba(60,143,255,0.07) 0%, transparent 50%), radial-gradient(ellipse at 20% 80%, rgba(60,143,255,0.04) 0%, transparent 50%), linear-gradient(135deg, #282828 0%, #1c2a3a 100%)',
11
- }}
12
- >
13
- {/* Decorative rings */}
14
- <div
15
- className="absolute inset-0 opacity-[0.06]"
16
- style={{
17
- backgroundImage:
18
- 'radial-gradient(circle at 70% 40%, transparent 20%, rgba(60,143,255,0.4) 20.5%, transparent 21%), radial-gradient(circle at 70% 40%, transparent 35%, rgba(60,143,255,0.3) 35.5%, transparent 36%), radial-gradient(circle at 70% 40%, transparent 50%, rgba(60,143,255,0.2) 50.5%, transparent 51%)',
19
- }}
20
- />
21
- <CardContent className="relative p-6 flex flex-col justify-between min-h-[200px]">
22
- <div>
23
- <h3 className="text-2xl font-bold leading-tight mb-3">
24
- Connect New
25
- <br />
26
- AI Models
27
- </h3>
28
- <span className="inline-flex items-center gap-1 px-2.5 py-1 rounded-full bg-destructive/15 text-destructive text-xs font-medium">
29
- +15% faster
30
- </span>
31
- <span className="text-xs text-muted-foreground ml-2">
32
- with parallel routing
33
- </span>
34
- </div>
35
- <div className="flex justify-end mt-4">
36
- <button className="flex items-center gap-2 px-5 py-2.5 rounded-full bg-primary text-primary-foreground text-sm font-medium hover:brightness-110 transition">
37
- Explore
38
- <ArrowUpRight className="h-4 w-4" />
39
- </button>
40
- </div>
41
- </CardContent>
42
- </Card>
43
- );
44
- }
@@ -1,35 +0,0 @@
1
- import { FileText, ArrowUpRight, X } from 'lucide-react';
2
- import { Card, CardContent } from '@/components/ui/card';
3
-
4
- export default function ReportCard() {
5
- return (
6
- <Card
7
- className="border-border overflow-hidden relative"
8
- style={{
9
- background:
10
- 'radial-gradient(circle at 30% 50%, rgba(253,72,107,0.2) 0%, transparent 45%), radial-gradient(circle at 80% 60%, rgba(253,72,107,0.12) 0%, transparent 40%), linear-gradient(135deg, #2a1a20 0%, #211518 100%)',
11
- }}
12
- >
13
- <CardContent className="relative p-6 flex flex-col justify-between h-full">
14
- {/* Icon buttons */}
15
- <div className="flex items-center gap-1.5 mb-4">
16
- <button className="flex items-center justify-center h-8 w-8 rounded-full bg-black/40 text-foreground/80 hover:text-foreground transition-colors">
17
- <FileText className="h-3.5 w-3.5" />
18
- </button>
19
- <button className="flex items-center justify-center h-8 w-8 rounded-full bg-black/40 text-foreground/80 hover:text-foreground transition-colors">
20
- <ArrowUpRight className="h-3.5 w-3.5" />
21
- </button>
22
- <button className="flex items-center justify-center h-8 w-8 rounded-full bg-black/40 text-foreground/80 hover:text-foreground transition-colors ml-auto">
23
- <X className="h-3.5 w-3.5" />
24
- </button>
25
- </div>
26
- <div>
27
- <h3 className="text-lg font-bold mb-1">System Report</h3>
28
- <p className="text-xs text-foreground/60 leading-relaxed">
29
- Generate and download a detailed report of your system
30
- </p>
31
- </div>
32
- </CardContent>
33
- </Card>
34
- );
35
- }
@@ -1,28 +0,0 @@
1
- import { ChevronDown } from 'lucide-react';
2
- import { Card, CardContent } from '@/components/ui/card';
3
-
4
- export default function TodayStats() {
5
- return (
6
- <Card className="bg-card border-border">
7
- <CardContent className="p-6 flex flex-col justify-between h-full">
8
- <div className="flex items-center gap-2 mb-4">
9
- <div className="flex items-center justify-center h-8 w-8 rounded-full border border-border">
10
- <ChevronDown className="h-4 w-4 text-muted-foreground" />
11
- </div>
12
- <span className="text-sm font-medium">
13
- Today&apos;s
14
- <br />
15
- Messages
16
- </span>
17
- </div>
18
- <div>
19
- <span className="text-4xl font-bold text-primary">342</span>
20
- <div className="flex items-center gap-1 mt-1">
21
- <span className="text-sm text-primary font-medium">+8%</span>
22
- <span className="text-xs text-muted-foreground">vs yesterday</span>
23
- </div>
24
- </div>
25
- </CardContent>
26
- </Card>
27
- );
28
- }
@@ -1,8 +0,0 @@
1
- export default function ConnectionStatus({ connected }: { connected: boolean }) {
2
- return (
3
- <div className="flex items-center gap-1.5">
4
- <div className={`w-2 h-2 rounded-full ${connected ? 'bg-green-500' : 'bg-red-500'}`} />
5
- <span className="text-xs text-slate-500">{connected ? 'Connected' : 'Disconnected'}</span>
6
- </div>
7
- );
8
- }
@@ -1,53 +0,0 @@
1
- import { Bell } from 'lucide-react';
2
- import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
3
- import { Avatar, AvatarFallback } from '@/components/ui/avatar';
4
- import MobileNav from './MobileNav';
5
-
6
- export default function DashboardHeader() {
7
- return (
8
- <header className="flex items-center justify-between px-4 md:px-6 py-3 md:py-4">
9
- {/* Left: hamburger (mobile) + logo */}
10
- <div className="flex items-center gap-3">
11
- <MobileNav />
12
- <div className="flex items-center gap-2">
13
- <img src="/fluxy.png" alt="Fluxy" className="h-6 w-auto" />
14
- <span className="font-semibold text-lg hidden sm:block">Fluxy</span>
15
- </div>
16
- </div>
17
-
18
- {/* Center: pill tabs (desktop only) */}
19
- <div className="hidden md:block">
20
- <Tabs defaultValue="overview">
21
- <TabsList className="bg-card rounded-full p-1 h-auto border border-border">
22
- {['Overview', 'Conversations', 'Models', 'Knowledge', 'Activity'].map(
23
- (tab) => (
24
- <TabsTrigger
25
- key={tab}
26
- value={tab.toLowerCase()}
27
- className="rounded-full px-5 py-2 text-sm data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-none"
28
- >
29
- {tab}
30
- </TabsTrigger>
31
- ),
32
- )}
33
- </TabsList>
34
- </Tabs>
35
- </div>
36
-
37
- {/* Right: actions */}
38
- <div className="flex items-center gap-2">
39
- <button className="relative flex items-center justify-center h-10 w-10 rounded-full bg-card border border-border text-muted-foreground hover:text-foreground transition-colors">
40
- <Bell className="h-4 w-4" />
41
- <span className="absolute -top-0.5 -right-0.5 flex items-center justify-center h-4 w-4 rounded-full bg-destructive text-[10px] font-medium text-white">
42
- 2
43
- </span>
44
- </button>
45
- <Avatar className="h-10 w-10 border border-border">
46
- <AvatarFallback className="bg-primary text-primary-foreground text-sm font-medium">
47
- F
48
- </AvatarFallback>
49
- </Avatar>
50
- </div>
51
- </header>
52
- );
53
- }
@@ -1,10 +0,0 @@
1
- import ConnectionStatus from './ConnectionStatus';
2
-
3
- export default function Header({ connected }: { connected: boolean }) {
4
- return (
5
- <header className="flex items-center justify-between px-4 py-3 border-b border-slate-800">
6
- <h1 className="text-sm font-semibold">Dashboard</h1>
7
- <ConnectionStatus connected={connected} />
8
- </header>
9
- );
10
- }