feat: improve AI Chat UX, add notebook summary, and fix shared/reminders routing
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m50s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m50s
This commit is contained in:
@@ -152,18 +152,18 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
return (
|
||||
<Button
|
||||
onClick={() => setIsOpen(true)}
|
||||
className="fixed bottom-6 right-6 h-12 w-12 rounded-full shadow-xl z-40 transition-transform hover:scale-105 bg-[#E9ECEF] text-[#1C1C1C] hover:bg-[#E9ECEF]/80 border border-black/5"
|
||||
className="fixed bottom-6 right-6 h-12 w-12 rounded-full shadow-xl z-40 transition-transform hover:scale-105 bg-muted text-foreground hover:bg-muted/80 border border-border"
|
||||
size="icon"
|
||||
title={t('ai.openAssistant')}
|
||||
>
|
||||
<Sparkles className="h-5 w-5" />
|
||||
<Sparkles className="h-5 w-5 text-memento-accent" />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<aside className={cn(
|
||||
"fixed bottom-20 right-6 border border-border/40 bg-[#FDFDFE] flex flex-col z-40 shadow-2xl rounded-2xl overflow-hidden transition-all duration-300",
|
||||
"fixed bottom-20 right-6 border border-border/40 bg-background flex flex-col z-40 shadow-2xl rounded-2xl overflow-hidden transition-all duration-300",
|
||||
isExpanded ? "w-[80vw] h-[85vh] max-w-[1200px]" : "h-[700px] max-h-[85vh] w-[360px]"
|
||||
)}>
|
||||
{/* Header */}
|
||||
@@ -207,7 +207,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
onClick={() => setActiveTab('chat')}
|
||||
className={cn(
|
||||
"flex-1 pb-3 border-b-2 text-sm font-semibold flex items-center justify-center gap-2 transition-all",
|
||||
activeTab === 'chat' ? "border-[#75B2D6] text-[#75B2D6]" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
activeTab === 'chat' ? "border-memento-blue text-memento-blue" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
<Bot className="h-4 w-4" /> {t('ai.chatTab')}
|
||||
@@ -216,7 +216,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
onClick={() => setActiveTab('insights')}
|
||||
className={cn(
|
||||
"flex-1 pb-3 border-b-2 text-sm font-semibold flex items-center justify-center gap-2 transition-all",
|
||||
activeTab === 'insights' ? "border-[#75B2D6] text-[#75B2D6]" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
activeTab === 'insights' ? "border-memento-blue text-memento-blue" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
<Sparkles className="h-4 w-4" /> {t('ai.insightsTab')}
|
||||
@@ -225,7 +225,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
onClick={() => setActiveTab('history')}
|
||||
className={cn(
|
||||
"flex-1 pb-3 border-b-2 text-sm font-semibold flex items-center justify-center gap-2 transition-all",
|
||||
activeTab === 'history' ? "border-[#75B2D6] text-[#75B2D6]" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
activeTab === 'history' ? "border-memento-blue text-memento-blue" : "border-transparent text-muted-foreground hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
<History className="h-4 w-4" /> {t('ai.historyTab')}
|
||||
@@ -239,10 +239,10 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
{/* AI Welcome Message */}
|
||||
{messages.length === 0 && (
|
||||
<div className="flex gap-3">
|
||||
<div className="w-8 h-8 rounded-full bg-[#75B2D6]/10 text-[#75B2D6] flex items-center justify-center flex-shrink-0 border border-[#75B2D6]/20">
|
||||
<div className="w-8 h-8 rounded-full bg-memento-blue/10 text-memento-blue flex items-center justify-center flex-shrink-0 border border-memento-blue/20">
|
||||
<Bot className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="bg-[#FDFDFE] border border-border/50 p-3.5 rounded-2xl rounded-tl-sm shadow-sm">
|
||||
<div className="bg-background border border-border/50 p-3.5 rounded-2xl rounded-tl-sm shadow-sm">
|
||||
<p className="text-sm text-foreground leading-relaxed">
|
||||
{t('ai.welcomeMsg')}
|
||||
</p>
|
||||
@@ -260,16 +260,16 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
<div className={cn(
|
||||
'w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 border text-[10px] font-bold',
|
||||
msg.role === 'user'
|
||||
? 'bg-zinc-100 border-zinc-200 text-zinc-600'
|
||||
: 'bg-[#75B2D6]/10 text-[#75B2D6] border-[#75B2D6]/20',
|
||||
? 'bg-muted border-border text-muted-foreground'
|
||||
: 'bg-memento-blue/10 text-memento-blue border-memento-blue/20',
|
||||
)}>
|
||||
{msg.role === 'user' ? 'U' : <Bot className="h-4 w-4" />}
|
||||
</div>
|
||||
<div className={cn(
|
||||
'max-w-[85%] p-3.5 rounded-2xl text-sm leading-relaxed shadow-sm',
|
||||
msg.role === 'user'
|
||||
? 'bg-[#75B2D6] text-white rounded-tr-sm'
|
||||
: 'bg-[#FDFDFE] border border-border/50 rounded-tl-sm text-foreground',
|
||||
? 'bg-memento-blue text-white rounded-tr-sm'
|
||||
: 'bg-background border border-border/50 rounded-tl-sm text-foreground',
|
||||
)}>
|
||||
{msg.role === 'assistant'
|
||||
? <MarkdownContent content={text} />
|
||||
@@ -281,10 +281,10 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
|
||||
{isLoading && (
|
||||
<div className="flex gap-3">
|
||||
<div className="w-8 h-8 rounded-full bg-[#75B2D6]/10 text-[#75B2D6] flex items-center justify-center flex-shrink-0 border border-[#75B2D6]/20">
|
||||
<div className="w-8 h-8 rounded-full bg-memento-blue/10 text-memento-blue flex items-center justify-center flex-shrink-0 border border-memento-blue/20">
|
||||
<Bot className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="bg-[#FDFDFE] border border-border/50 p-3.5 rounded-2xl rounded-tl-sm shadow-sm">
|
||||
<div className="bg-background border border-border/50 p-3.5 rounded-2xl rounded-tl-sm shadow-sm">
|
||||
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -295,7 +295,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
|
||||
{activeTab === 'insights' && (
|
||||
<div className="h-full">
|
||||
<h3 className="text-sm font-semibold mb-4 flex items-center gap-2"><Sparkles className="h-4 w-4 text-[#75B2D6]" /> {t('ai.summaryLast5')}</h3>
|
||||
<h3 className="text-sm font-semibold mb-4 flex items-center gap-2"><Sparkles className="h-4 w-4 text-memento-accent" /> {t('ai.summaryLast5')}</h3>
|
||||
{insightsLoading ? (
|
||||
<div className="flex flex-col items-center justify-center py-10 opacity-60">
|
||||
<Loader2 className="h-8 w-8 animate-spin mb-4 text-muted-foreground" />
|
||||
@@ -323,7 +323,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
history.map(conv => (
|
||||
<button
|
||||
key={conv.id}
|
||||
className="w-full text-left p-3 rounded-xl border border-border/50 hover:bg-muted/50 hover:border-[#75B2D6]/30 transition-all flex flex-col gap-1"
|
||||
className="w-full text-left p-3 rounded-xl border border-border/50 hover:bg-muted/50 hover:border-memento-blue/30 transition-all flex flex-col gap-1"
|
||||
onClick={() => {
|
||||
setConversationId(conv.id)
|
||||
setMessages(conv.messages.map((m: any) => ({
|
||||
@@ -350,12 +350,12 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
</div>
|
||||
|
||||
{/* Input Area & Tone Controls (Only in Chat tab) */}
|
||||
<div className={cn("p-4 border-t border-border/40 bg-[#FDFDFE] shrink-0", activeTab !== 'chat' && "hidden")}>
|
||||
<div className={cn("p-4 border-t border-border/40 bg-background shrink-0", activeTab !== 'chat' && "hidden")}>
|
||||
{/* Context Scope */}
|
||||
<div className="mb-3">
|
||||
<span className="text-[9px] font-bold uppercase tracking-widest text-muted-foreground block mb-1.5 ml-1">{t('ai.discussionContextLabel')}</span>
|
||||
<Select value={chatScope} onValueChange={setChatScope}>
|
||||
<SelectTrigger className="h-8 text-xs bg-[#FDFDFE] border-border/60">
|
||||
<SelectTrigger className="h-8 text-xs bg-background border-border/60">
|
||||
<SelectValue placeholder={t('ai.selectNotebook')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -392,8 +392,8 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
className={cn(
|
||||
"py-1 rounded-md border text-[10px] font-medium transition-all flex flex-col items-center justify-center gap-0.5",
|
||||
isSelected
|
||||
? "border-[#75B2D6] bg-[#75B2D6]/10 text-[#75B2D6] shadow-sm"
|
||||
: "border-border/60 bg-[#FDFDFE] text-muted-foreground hover:bg-muted hover:border-border"
|
||||
? "border-memento-blue bg-memento-blue/10 text-memento-blue shadow-sm"
|
||||
: "border-border/60 bg-background text-muted-foreground hover:bg-muted hover:border-border"
|
||||
)}
|
||||
>
|
||||
<Icon className="h-3 w-3" />
|
||||
@@ -405,7 +405,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
</div>
|
||||
|
||||
{/* Text Input */}
|
||||
<div className="relative bg-[#FDFDFE] border border-border/60 rounded-xl p-1 focus-within:border-[#75B2D6] focus-within:ring-1 focus-within:ring-[#75B2D6]/20 transition-all shadow-sm">
|
||||
<div className="relative bg-background border border-border/60 rounded-xl p-1 focus-within:border-memento-blue focus-within:ring-1 focus-within:ring-memento-blue/20 transition-all shadow-sm">
|
||||
<textarea
|
||||
className="w-full bg-transparent border-none focus:ring-0 resize-none text-sm text-foreground placeholder:text-muted-foreground/70 p-2 min-h-[60px] max-h-[120px]"
|
||||
placeholder={t('ai.chatPlaceholder')}
|
||||
@@ -440,7 +440,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
|
||||
) : (
|
||||
<Button
|
||||
size="icon"
|
||||
className="h-8 w-8 rounded-lg bg-[#75B2D6] text-white shadow-sm hover:shadow-md transition-all"
|
||||
className="h-8 w-8 rounded-lg bg-memento-blue text-white shadow-sm hover:shadow-md transition-all"
|
||||
onClick={handleSend}
|
||||
disabled={!input.trim()}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user