feat(market): add Minha Intenções tab with panel, hook, and badge
- Introduced "Minhas Intenções" tab visible only to logged-in users. - Integrated MyPurchaseIntentionsPanel and useMyPurchaseIntentions hook. - Added tab badge showing count of pending intentions. - Extended session API to include user’s main character for downstream features.
This commit is contained in:
1 parent
f35fee944d
commit
7f42def478
55 files changed
+4906
-95
No files matched your search
@@ -0,0 +1,88 @@
|
||||
"use client";
|
||||
|
||||
import { useState, KeyboardEvent } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Send, Loader2 } from "lucide-react";
|
||||
import { useChatTyping } from "@/lib/hooks/use-chat";
|
||||
import { useSocket } from "@/lib/hooks/use-socket";
|
||||
|
||||
interface MessageInputProps {
|
||||
onSend: (content: string) => Promise<void>;
|
||||
isSending: boolean;
|
||||
disabled?: boolean;
|
||||
chatId: string | null;
|
||||
}
|
||||
|
||||
export function MessageInput({
|
||||
onSend,
|
||||
isSending,
|
||||
disabled = false,
|
||||
chatId,
|
||||
}: MessageInputProps) {
|
||||
const [content, setContent] = useState("");
|
||||
const { socket, isConnected } = useSocket();
|
||||
const { handleTypingStart, handleTypingStop } = useChatTyping(
|
||||
socket,
|
||||
isConnected,
|
||||
chatId
|
||||
);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!content.trim() || isSending || disabled) return;
|
||||
|
||||
const messageContent = content.trim();
|
||||
setContent("");
|
||||
handleTypingStop();
|
||||
await onSend(messageContent);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
setContent(value);
|
||||
|
||||
if (value.trim().length > 0) {
|
||||
handleTypingStart();
|
||||
} else {
|
||||
handleTypingStop();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="border-t p-4">
|
||||
<div className="flex items-end gap-2">
|
||||
<Textarea
|
||||
value={content}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Digite sua mensagem... (Enter para enviar, Shift+Enter para nova linha)"
|
||||
className="min-h-[60px] max-h-[120px] resize-none"
|
||||
disabled={isSending || disabled}
|
||||
rows={2}
|
||||
/>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
disabled={!content.trim() || isSending || disabled}
|
||||
size="icon"
|
||||
className="h-[60px] w-[60px] flex-shrink-0"
|
||||
>
|
||||
{isSending ? (
|
||||
<Loader2 className="h-5 w-5 animate-spin" />
|
||||
) : (
|
||||
<Send className="h-5 w-5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
Máximo 1000 caracteres
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user