bloby-bot 0.37.1 → 0.39.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/package.json +1 -1
- package/supervisor/harnesses/codex.ts +34 -0
- package/worker/prompts/bloby-system-prompt.txt +2 -2
- package/workspace/client/index.html +3 -0
- package/workspace/client/public/.well-known/assetlinks.json +8 -0
- package/workspace/client/public/bloby-cyberpunk.png +0 -0
- package/workspace/client/public/brand/blackrock.svg +8 -0
- package/workspace/client/public/kid-breakfast.png +0 -0
- package/workspace/client/public/wallpapers/bg.jpg +0 -0
- package/workspace/client/public/wallpapers/crypto_bg.png +0 -0
- package/workspace/client/public/wallpapers/wp-dusk.jpg +0 -0
- package/workspace/client/public/wallpapers/wp-mountain.jpg +0 -0
- package/workspace/client/public/wallpapers/wp-ocean.jpg +0 -0
- package/workspace/client/src/App.tsx +20 -9
- package/workspace/client/src/components/Dashboard/AiChatPage.tsx +145 -0
- package/workspace/client/src/components/Dashboard/CryptoPage.tsx +470 -0
- package/workspace/client/src/components/Dashboard/DashboardPage.tsx +117 -113
- package/workspace/client/src/components/Dashboard/WishlistPage.tsx +464 -0
- package/workspace/client/src/components/Layout/DashboardLayout.tsx +32 -34
- package/workspace/client/src/components/Layout/MiniSidebar.tsx +64 -0
- package/workspace/client/src/components/Layout/MobileNav.tsx +103 -6
- package/workspace/client/src/components/Layout/Sidebar.tsx +11 -10
- package/workspace/client/src/components/Lock/PinInput.tsx +107 -0
- package/workspace/client/src/components/Lock/WorkspaceLock.tsx +484 -0
- package/workspace/client/src/components/StickyNotes/StickyNotesOverlay.tsx +396 -0
- package/workspace/client/src/components/StickyNotes/StickyNotesSettingsPage.tsx +427 -0
- package/workspace/client/src/components/Wallpaper/WallpaperBackground.tsx +12 -0
- package/workspace/client/src/components/Wallpaper/WallpaperContext.tsx +160 -0
- package/workspace/client/src/components/Wallpaper/WallpaperPicker.tsx +67 -0
- package/workspace/client/src/styles/globals.css +89 -4
|
@@ -1,134 +1,138 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router';
|
|
3
|
+
import { Heart, Zap, Eye, ArrowUpRight } from 'lucide-react';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const rev = [{ v: 82 }, { v: 89 }, { v: 94 }, { v: 101 }, { v: 108 }, { v: 112 }, { v: 125 }];
|
|
10
|
-
const fol = [{ v: 12 }, { v: 18 }, { v: 9 }, { v: 24 }, { v: 31 }, { v: 19 }, { v: 27 }];
|
|
11
|
-
|
|
12
|
-
function StripeSvg() {
|
|
13
|
-
return <svg className="h-3.5 w-3.5 text-[#635BFF]" viewBox="0 0 24 24" fill="currentColor"><path d="M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.591-7.305z" /></svg>;
|
|
14
|
-
}
|
|
15
|
-
function GmailSvg() {
|
|
16
|
-
return <svg className="h-3.5 w-3.5 text-[#EA4335]" viewBox="0 0 24 24" fill="currentColor"><path d="M24 5.457v13.909c0 .904-.732 1.636-1.636 1.636h-3.819V11.73L12 16.64l-6.545-4.91v9.273H1.636A1.636 1.636 0 0 1 0 19.366V5.457c0-2.023 2.309-3.178 3.927-1.964L5.455 4.64 12 9.548l6.545-4.91 1.528-1.145C21.69 2.28 24 3.434 24 5.457z" /></svg>;
|
|
5
|
+
interface WishlistStats {
|
|
6
|
+
total: number;
|
|
7
|
+
watching: number;
|
|
8
|
+
urgent: number;
|
|
9
|
+
purchased: number;
|
|
17
10
|
}
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
|
|
12
|
+
interface WishlistItem {
|
|
13
|
+
id: number;
|
|
14
|
+
name: string;
|
|
15
|
+
last_deal_found: string | null;
|
|
16
|
+
created_at: string;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
export default function DashboardPage() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
className="text-xl sm:text-2xl font-bold mb-1 tracking-tight w-fit"
|
|
27
|
-
style={{ backgroundImage: GRADIENT, WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}
|
|
28
|
-
>
|
|
29
|
-
Let's get started
|
|
30
|
-
</h1>
|
|
31
|
-
<p className="text-muted-foreground text-xs mb-6">Your workspace at a glance.</p>
|
|
20
|
+
const navigate = useNavigate();
|
|
21
|
+
const [wlStats, setWlStats] = useState<WishlistStats | null>(null);
|
|
22
|
+
const [wlLatestDeal, setWlLatestDeal] = useState<{ name: string; deal: string } | null>(null);
|
|
32
23
|
|
|
33
|
-
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
fetch('/app/api/wishlist/stats')
|
|
26
|
+
.then((r) => (r.ok ? r.json() : null))
|
|
27
|
+
.then((s) => { if (s) setWlStats(s); })
|
|
28
|
+
.catch(() => {});
|
|
29
|
+
fetch('/app/api/wishlist')
|
|
30
|
+
.then((r) => (r.ok ? r.json() : null))
|
|
31
|
+
.then((items: WishlistItem[] | null) => {
|
|
32
|
+
if (!items) return;
|
|
33
|
+
const withDeal = items.find((i) => i.last_deal_found);
|
|
34
|
+
if (withDeal) setWlLatestDeal({ name: withDeal.name, deal: withDeal.last_deal_found! });
|
|
35
|
+
})
|
|
36
|
+
.catch(() => {});
|
|
37
|
+
}, []);
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
return (
|
|
40
|
+
<div className="flex flex-col h-full px-4 sm:px-6 md:px-20 pt-10 sm:pt-16 pb-32 max-w-5xl mx-auto w-full">
|
|
41
|
+
<div className="grid grid-cols-1 gap-5">
|
|
42
|
+
|
|
43
|
+
{/* Wishlist — glass card */}
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
onClick={() => navigate('/wishlist')}
|
|
47
|
+
className="glass-card text-left cursor-pointer hover:brightness-110 transition group p-6 sm:p-7"
|
|
48
|
+
>
|
|
49
|
+
<div className="relative">
|
|
50
|
+
<div className="flex items-start gap-4 mb-6">
|
|
51
|
+
<div className="h-12 w-12 rounded-2xl flex items-center justify-center bg-gradient-to-br from-pink-300/40 to-rose-500/20 border border-white/10 backdrop-blur-xl shrink-0">
|
|
52
|
+
<Heart className="h-5 w-5 text-pink-200" fill="currentColor" />
|
|
43
53
|
</div>
|
|
44
|
-
<div className="flex
|
|
45
|
-
<
|
|
46
|
-
<
|
|
54
|
+
<div className="flex-1 min-w-0">
|
|
55
|
+
<h3 className="text-base font-semibold text-white tracking-tight">Wishlist</h3>
|
|
56
|
+
<p className="text-xs text-white/60 mt-0.5">Items you're tracking, urgent picks, and the latest deal.</p>
|
|
57
|
+
</div>
|
|
58
|
+
<div className="h-9 w-9 rounded-full bg-white/10 border border-white/10 flex items-center justify-center text-white/80 group-hover:bg-white/15 transition">
|
|
59
|
+
<ArrowUpRight className="h-4 w-4" />
|
|
47
60
|
</div>
|
|
48
61
|
</div>
|
|
49
|
-
<p className="text-2xl font-bold tracking-tight mt-2">$12,480</p>
|
|
50
|
-
<p className="text-[10px] text-muted-foreground/50 mb-1">MRR</p>
|
|
51
|
-
<div className="h-12 overflow-hidden">
|
|
52
|
-
<ResponsiveContainer width="100%" height={48}>
|
|
53
|
-
<AreaChart data={rev}>
|
|
54
|
-
<defs>
|
|
55
|
-
<linearGradient id="sg" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stopColor="#4FF2FE" /><stop offset="50%" stopColor="#BC20DE" /><stop offset="100%" stopColor="#FE546B" /></linearGradient>
|
|
56
|
-
<linearGradient id="sf" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stopColor="#BC20DE" stopOpacity={0.12} /><stop offset="100%" stopColor="#BC20DE" stopOpacity={0} /></linearGradient>
|
|
57
|
-
</defs>
|
|
58
|
-
<Area type="monotone" dataKey="v" stroke="url(#sg)" strokeWidth={1.5} fill="url(#sf)" />
|
|
59
|
-
</AreaChart>
|
|
60
|
-
</ResponsiveContainer>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
<div className="grid grid-cols-3 gap-3 sm:gap-5">
|
|
64
|
+
<Stat
|
|
65
|
+
icon={Eye}
|
|
66
|
+
label="Watching"
|
|
67
|
+
value={wlStats?.watching ?? 0}
|
|
68
|
+
gradientFrom="#5DE0E6"
|
|
69
|
+
gradientTo="#85C7FF"
|
|
70
|
+
/>
|
|
71
|
+
<Stat
|
|
72
|
+
icon={Zap}
|
|
73
|
+
label="Urgent"
|
|
74
|
+
value={wlStats?.urgent ?? 0}
|
|
75
|
+
gradientFrom="#FFB37A"
|
|
76
|
+
gradientTo="#FF7AAA"
|
|
77
|
+
/>
|
|
78
|
+
<Stat
|
|
79
|
+
icon={Heart}
|
|
80
|
+
label="Total"
|
|
81
|
+
value={wlStats?.total ?? 0}
|
|
82
|
+
gradientFrom="#C9A7E8"
|
|
83
|
+
gradientTo="#F2B5C7"
|
|
84
|
+
/>
|
|
77
85
|
</div>
|
|
78
|
-
<div className="h-10 overflow-hidden">
|
|
79
|
-
<ResponsiveContainer width="100%" height={40}>
|
|
80
|
-
<BarChart data={fol} barCategoryGap="25%">
|
|
81
|
-
<defs>
|
|
82
|
-
<linearGradient id="xg" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stopColor="#BC20DE" stopOpacity={0.3} /><stop offset="100%" stopColor="#4FF2FE" stopOpacity={0.05} /></linearGradient>
|
|
83
|
-
</defs>
|
|
84
|
-
<Bar dataKey="v" fill="url(#xg)" radius={[2, 2, 0, 0]} />
|
|
85
|
-
</BarChart>
|
|
86
|
-
</ResponsiveContainer>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</div>
|
|
100
|
-
{['Sarah Chen', 'Stripe', 'Alex R.'].map((n) => (
|
|
101
|
-
<div key={n} className="flex items-center gap-2 py-1.5">
|
|
102
|
-
<div className="h-5 w-5 rounded-full bg-white/[0.06] text-[9px] font-bold flex items-center justify-center shrink-0">{n[0]}</div>
|
|
103
|
-
<span className="text-[11px] truncate">{n}</span>
|
|
87
|
+
{wlLatestDeal && (
|
|
88
|
+
<div className="mt-6 pt-5 border-t border-white/10 flex items-start gap-3">
|
|
89
|
+
<div className="h-7 px-2 rounded-full bg-amber-300/15 border border-amber-200/20 text-amber-200 text-[10px] font-semibold uppercase tracking-wider flex items-center">
|
|
90
|
+
Latest deal
|
|
91
|
+
</div>
|
|
92
|
+
<p className="text-sm text-white/85 truncate flex-1">
|
|
93
|
+
<span className="text-white/55">{wlLatestDeal.name}:</span> {wlLatestDeal.deal}
|
|
94
|
+
</p>
|
|
104
95
|
</div>
|
|
105
|
-
)
|
|
96
|
+
)}
|
|
106
97
|
</div>
|
|
107
|
-
</
|
|
98
|
+
</button>
|
|
108
99
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<div className="flex items-center gap-2 mb-2.5">
|
|
114
|
-
<div className="h-7 w-7 rounded-lg bg-[#9235F9]/10 flex items-center justify-center"><Search className="h-3.5 w-3.5 text-[#9235F9]" /></div>
|
|
115
|
-
<span className="text-xs font-bold">Research</span>
|
|
116
|
-
<span className="ml-auto text-[10px] font-bold text-muted-foreground bg-white/[0.06] px-2 py-0.5 rounded-full">3</span>
|
|
117
|
-
</div>
|
|
118
|
-
{[
|
|
119
|
-
{ t: 'Competitor pricing', s: 'Done', c: 'text-emerald-500 bg-emerald-500/10' },
|
|
120
|
-
{ t: 'Market trends Q1', s: 'Done', c: 'text-emerald-500 bg-emerald-500/10' },
|
|
121
|
-
{ t: 'User feedback', s: 'Review', c: 'text-orange-400 bg-orange-400/10' },
|
|
122
|
-
].map((r) => (
|
|
123
|
-
<div key={r.t} className="flex items-center justify-between py-1.5">
|
|
124
|
-
<span className="text-[11px]">{r.t}</span>
|
|
125
|
-
<span className={`text-[9px] font-bold px-1.5 py-0.5 rounded-full ${r.c}`}>{r.s}</span>
|
|
126
|
-
</div>
|
|
127
|
-
))}
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
130
104
|
|
|
105
|
+
function Stat({
|
|
106
|
+
icon: Icon,
|
|
107
|
+
label,
|
|
108
|
+
value,
|
|
109
|
+
gradientFrom,
|
|
110
|
+
gradientTo,
|
|
111
|
+
}: {
|
|
112
|
+
icon: React.ComponentType<{ className?: string }>;
|
|
113
|
+
label: string;
|
|
114
|
+
value: number;
|
|
115
|
+
gradientFrom: string;
|
|
116
|
+
gradientTo: string;
|
|
117
|
+
}) {
|
|
118
|
+
const gradient = `linear-gradient(135deg, ${gradientFrom}, ${gradientTo})`;
|
|
119
|
+
return (
|
|
120
|
+
<div className="relative">
|
|
121
|
+
<div className="flex items-center gap-1.5 mb-2">
|
|
122
|
+
<Icon className="h-3 w-3 text-white/70" />
|
|
123
|
+
<span
|
|
124
|
+
className="text-[10px] font-semibold uppercase tracking-wider"
|
|
125
|
+
style={{
|
|
126
|
+
backgroundImage: gradient,
|
|
127
|
+
WebkitBackgroundClip: 'text',
|
|
128
|
+
WebkitTextFillColor: 'transparent',
|
|
129
|
+
backgroundClip: 'text',
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
{label}
|
|
133
|
+
</span>
|
|
131
134
|
</div>
|
|
135
|
+
<p className="text-3xl sm:text-4xl font-semibold tracking-tight text-white tabular-nums">{value}</p>
|
|
132
136
|
</div>
|
|
133
137
|
);
|
|
134
138
|
}
|