Skip to content

Commit 65cb7c3

Browse files
committed
fix(dashboard): fix full-height layout, pinned chat input, spacious schema canvas nodes, and refined boilerplate prompts without emojis
1 parent f239522 commit 65cb7c3

5 files changed

Lines changed: 512 additions & 734 deletions

File tree

‎apps/web-dashboard/src/components/CollectionCreatorAgent.jsx‎

Lines changed: 34 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import { Send, ArrowRight } from 'lucide-react';
55
import SchemaCanvasViewer from './SchemaCanvasViewer';
66

77
const SUGGESTIONS = [
8-
{ label: '🛒 E-commerce store', prompt: 'Create an e-commerce platform with products, categories, orders, and customer reviews' },
9-
{ label: '📋 Project management', prompt: 'Build a project management tool with workspaces, tasks, milestones, and time tracking' },
10-
{ label: '📝 Blog platform', prompt: 'Design a blog with posts, authors, tags, comments, and draft management' },
11-
{ label: '🎓 Learning platform', prompt: 'Create a learning platform with courses, modules, lessons, quizzes, and student enrollments' },
8+
{ label: 'E-commerce Platform', prompt: 'Create an e-commerce platform with products, categories, orders, customers, and product reviews' },
9+
{ label: 'Project Management SaaS', prompt: 'Build a project management system with workspaces, projects, tasks, milestones, and team members' },
10+
{ label: 'Subscription Billing API', prompt: 'Design a subscription service with plans, subscriptions, invoices, payment methods, and usage logs' },
11+
{ label: 'Content Management (CMS)', prompt: 'Design a headless CMS with articles, authors, categories, media assets, and publishing revisions' },
1212
];
1313

1414
const createMsg = (role, content) => ({
@@ -19,7 +19,7 @@ const createMsg = (role, content) => ({
1919

2020
export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
2121
const [messages, setMessages] = useState([
22-
createMsg('assistant', "Hi! Tell me what you're building — for example: 'a food delivery app' or 'a SaaS project management tool' — and I'll design a MongoDB schema for you.")
22+
createMsg('assistant', "Describe what you're building — for example: a multi-tenant SaaS, an e-commerce platform, or a workflow tool — and I will design a production-ready MongoDB schema for you.")
2323
]);
2424
const [aiStatus, setAiStatus] = useState('idle'); // 'idle' | 'loading' | 'error'
2525
const [schema, setSchema] = useState(null);
@@ -106,7 +106,7 @@ export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
106106
try {
107107
await api.delete(`/api/projects/${projectId}/ai/collection-creator/session`);
108108
setMessages([
109-
createMsg('assistant', "Hi! Tell me what you're building — for example: 'a food delivery app' or 'a SaaS project management tool' — and I'll design a MongoDB schema for you.")
109+
createMsg('assistant', "Describe what you're building — for example: a multi-tenant SaaS, an e-commerce platform, or a workflow tool — and I will design a production-ready MongoDB schema for you.")
110110
]);
111111
setSchema(null);
112112
setInsertResults(null);
@@ -214,37 +214,30 @@ export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
214214
};
215215

216216
return (
217-
<div className="flex flex-col lg:flex-row gap-8 h-[calc(100vh-170px)] min-h-[580px] font-sans">
217+
<div className="flex flex-col lg:flex-row gap-5 h-full w-full font-sans overflow-hidden">
218218

219-
{/* Open Chat Stream & Floating Composer - Left */}
220-
<div className="flex flex-col flex-1 h-full relative" style={{ display: 'flex', flexDirection: 'column' }}>
219+
{/* Open Chat Stream & Pinned Composer - Left */}
220+
<div className="flex flex-col flex-1 h-full min-w-0 overflow-hidden relative">
221221

222-
{/* Messages Stream (No container box) */}
222+
{/* Messages Stream (Only this scrolls) */}
223223
<div
224-
className="flex-1 overflow-y-auto custom-scrollbar"
225-
style={{
226-
paddingRight: '1rem',
227-
paddingBottom: '1rem',
228-
display: 'flex',
229-
flexDirection: 'column',
230-
gap: '1.25rem'
231-
}}
224+
className="flex-1 overflow-y-auto custom-scrollbar pr-2 flex flex-col gap-3 min-h-0"
232225
>
233226
{messages.map((msg) => (
234227
<div key={msg.id} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
235228
<div
236229
style={{
237230
maxWidth: '85%',
238-
padding: '14px 20px',
239-
fontSize: '0.9rem',
240-
lineHeight: '1.6',
241-
borderRadius: '18px',
242-
borderBottomRightRadius: msg.role === 'user' ? '4px' : '18px',
243-
borderBottomLeftRadius: msg.role === 'assistant' ? '4px' : '18px',
231+
padding: '10px 16px',
232+
fontSize: '0.85rem',
233+
lineHeight: '1.55',
234+
borderRadius: '14px',
235+
borderBottomRightRadius: msg.role === 'user' ? '3px' : '14px',
236+
borderBottomLeftRadius: msg.role === 'assistant' ? '3px' : '14px',
244237
backgroundColor: msg.role === 'user' ? 'var(--color-primary)' : 'var(--color-bg-card)',
245238
color: msg.role === 'user' ? '#000' : 'var(--color-text-main)',
246239
border: msg.role === 'assistant' ? '1px solid var(--color-border)' : 'none',
247-
boxShadow: msg.role === 'assistant' ? '0 2px 10px rgba(0,0,0,0.06)' : '0 4px 14px rgba(62,207,142,0.25)',
240+
boxShadow: msg.role === 'assistant' ? '0 1px 4px rgba(0,0,0,0.05)' : '0 2px 8px rgba(62,207,142,0.2)',
248241
whiteSpace: 'pre-wrap'
249242
}}
250243
>
@@ -255,46 +248,21 @@ export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
255248

256249
{/* Quick Start Suggestions on empty chat */}
257250
{messages.length <= 1 && !schema && (
258-
<div style={{ marginTop: '0.5rem', display: 'flex', flexDirection: 'column', gap: '8px' }}>
259-
<span style={{ fontSize: '0.75rem', fontWeight: 600, color: 'var(--color-text-muted)', textTransform: 'uppercase', letterSpacing: '0.05em', paddingLeft: '4px' }}>
251+
<div className="mt-1 flex flex-col gap-2">
252+
<span className="text-[10px] font-semibold text-[var(--color-text-muted)] uppercase tracking-wider pl-1">
260253
Quick Start Ideas
261254
</span>
262-
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: '8px' }}>
255+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
263256
{SUGGESTIONS.map((s, i) => (
264257
<button
265258
key={i}
266259
type="button"
267260
onClick={() => sendMessage(null, s.prompt)}
268261
disabled={aiStatus === 'loading' || iterationsLeft === 0}
269-
style={{
270-
textAlign: 'left',
271-
padding: '10px 14px',
272-
backgroundColor: 'var(--color-bg-card)',
273-
border: '1px solid var(--color-border)',
274-
borderRadius: '12px',
275-
fontSize: '0.825rem',
276-
color: 'var(--color-text-main)',
277-
cursor: (aiStatus === 'loading' || iterationsLeft === 0) ? 'not-allowed' : 'pointer',
278-
opacity: (aiStatus === 'loading' || iterationsLeft === 0) ? 0.45 : 1,
279-
transition: 'all 0.2s ease',
280-
display: 'flex',
281-
alignItems: 'center',
282-
justifyContent: 'space-between',
283-
gap: '8px'
284-
}}
285-
onMouseEnter={(e) => {
286-
if (aiStatus !== 'loading' && iterationsLeft !== 0) {
287-
e.currentTarget.style.borderColor = 'var(--color-primary)';
288-
e.currentTarget.style.transform = 'translateY(-1px)';
289-
}
290-
}}
291-
onMouseLeave={(e) => {
292-
e.currentTarget.style.borderColor = 'var(--color-border)';
293-
e.currentTarget.style.transform = 'translateY(0)';
294-
}}
262+
className="text-left p-2.5 px-3 bg-[var(--color-bg-card)] border border-[var(--color-border)] hover:border-[var(--color-primary)] rounded-lg text-xs text-[var(--color-text-main)] flex items-center justify-between gap-2 transition-all cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
295263
>
296-
<span>{s.label}</span>
297-
<ArrowRight size={13} style={{ opacity: 0.6, flexShrink: 0 }} />
264+
<span className="truncate">{s.label}</span>
265+
<ArrowRight size={12} className="opacity-50 shrink-0" />
298266
</button>
299267
))}
300268
</div>
@@ -303,20 +271,9 @@ export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
303271

304272
{aiStatus === 'loading' && (
305273
<div className="flex justify-start">
306-
<div
307-
style={{
308-
backgroundColor: 'var(--color-bg-card)',
309-
padding: '12px 20px',
310-
borderRadius: '18px',
311-
borderBottomLeftRadius: '4px',
312-
border: '1px solid var(--color-border)',
313-
display: 'flex',
314-
alignItems: 'center',
315-
gap: '10px'
316-
}}
317-
>
318-
<div className="spinner-small" style={{ width: '14px', height: '14px', borderTopColor: 'var(--color-primary)' }}></div>
319-
<span style={{ fontSize: '0.85rem', color: 'var(--color-text-muted)', fontWeight: 500 }}>
274+
<div className="bg-[var(--color-bg-card)] p-2.5 px-4 rounded-xl rounded-bl-sm border border-[var(--color-border)] flex items-center gap-2.5 shadow-sm">
275+
<div className="spinner-small w-3.5 h-3.5 border-t-[var(--color-primary)]"></div>
276+
<span className="text-xs text-[var(--color-text-muted)] font-medium">
320277
AI is designing your schema...
321278
</span>
322279
</div>
@@ -325,67 +282,30 @@ export default function CollectionCreatorAgent({ projectId, onInsertAll }) {
325282
<div ref={messagesEndRef} />
326283
</div>
327284

328-
{/* Floating Bottom Composer */}
329-
<div style={{ marginTop: 'auto', paddingTop: '12px', flexShrink: 0 }}>
285+
{/* Pinned Bottom Composer */}
286+
<div className="mt-auto pt-2 flex-shrink-0">
330287
<div
331-
style={{
332-
position: 'relative',
333-
display: 'flex',
334-
alignItems: 'flex-end',
335-
backgroundColor: 'var(--color-bg-card)',
336-
border: '1px solid var(--color-border)',
337-
borderRadius: '20px',
338-
padding: '10px 14px 10px 20px',
339-
boxShadow: '0 8px 32px rgba(0,0,0,0.25)',
340-
transition: 'border-color 0.2s ease, box-shadow 0.2s ease'
341-
}}
288+
className="relative flex items-end bg-[var(--color-bg-card)] border border-[var(--color-border)] rounded-xl p-2 px-3 shadow-lg transition-all focus-within:border-[var(--color-primary)]"
342289
>
343290
<textarea
344291
ref={textareaRef}
345292
value={inputValue}
346293
onChange={(e) => setInputValue(e.target.value)}
347294
onKeyDown={handleKeyDown}
348295
disabled={aiStatus === 'loading' || (iterationsLeft === 0)}
349-
placeholder={iterationsLeft === 0 ? "Turn limit reached. Add Groq key in Settings." : "Describe your app (e.g. e-commerce, project management, todo app...)"}
296+
placeholder={iterationsLeft === 0 ? "Turn limit reached. Add Groq key in Settings." : "Describe your app (e.g. e-commerce store, booking system, CRM...)"}
350297
aria-label="Message the schema assistant"
351298
rows={1}
352-
style={{
353-
width: '100%',
354-
background: 'transparent',
355-
border: 'none',
356-
outline: 'none',
357-
color: 'var(--color-text-main)',
358-
fontSize: '0.9rem',
359-
lineHeight: '1.5',
360-
resize: 'none',
361-
maxHeight: '130px',
362-
minHeight: '26px',
363-
padding: '4px 0'
364-
}}
299+
className="w-full bg-transparent border-0 outline-none text-[var(--color-text-main)] text-xs leading-relaxed resize-none max-h-[100px] min-h-[24px] py-1 placeholder:text-[var(--color-text-muted)]"
365300
/>
366301
<button
367302
type="button"
368303
onClick={sendMessage}
369304
disabled={!inputValue.trim() || aiStatus === 'loading' || (iterationsLeft === 0)}
370-
style={{
371-
display: 'flex',
372-
alignItems: 'center',
373-
justifyContent: 'center',
374-
width: '36px',
375-
height: '36px',
376-
borderRadius: '50%',
377-
backgroundColor: (inputValue.trim() && aiStatus !== 'loading' && iterationsLeft !== 0) ? 'var(--color-primary)' : 'var(--color-bg-input)',
378-
color: (inputValue.trim() && aiStatus !== 'loading' && iterationsLeft !== 0) ? '#000' : 'var(--color-text-muted)',
379-
border: '1px solid var(--color-border)',
380-
cursor: (inputValue.trim() && aiStatus !== 'loading' && iterationsLeft !== 0) ? 'pointer' : 'default',
381-
opacity: (!inputValue.trim() || aiStatus === 'loading' || iterationsLeft === 0) ? 0.4 : 1,
382-
transition: 'all 0.2s ease',
383-
flexShrink: 0,
384-
marginLeft: '10px'
385-
}}
305+
className="flex items-center justify-center w-7 h-7 rounded-lg bg-[var(--color-primary)] text-black border-0 cursor-pointer disabled:opacity-35 disabled:cursor-not-allowed transition-all shrink-0 ml-2"
386306
title="Send message (Enter)"
387307
>
388-
<Send size={15} />
308+
<Send size={13} />
389309
</button>
390310
</div>
391311
{getIterationsBadge()}

0 commit comments

Comments
 (0)