File size: 4,344 Bytes
e454383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"use client";

import React, { useCallback, useEffect, useState, useRef } from "react";
import { Textarea } from "@/components/ui/textarea-chat";
import { Send, Loader2, Sparkles } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useChatLogic } from "@/hooks/useChatLogic";

import type { Chat } from "@/lib/types";

type Props = {
  selectedChat: Chat | null;
  selectedChatId: string | null;
  scrollToBottom: () => void;
};

const MessageBar: React.FC<Props> = ({
  selectedChat,
  selectedChatId,
  scrollToBottom,
}) => {
  const { isLoading, handleSubmit } = useChatLogic(
    selectedChat,
    selectedChatId,
    scrollToBottom
  );

  const [input, setInput] = useState<string>("");
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  // Auto-resize function
  const adjustTextareaHeight = useCallback(() => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = "auto";
      const newHeight = Math.min(textarea.scrollHeight, 120); // Reduced max height for mobile
      textarea.style.height = `${newHeight}px`;
    }
  }, []);

  useEffect(() => {
    adjustTextareaHeight();
  }, [input, adjustTextareaHeight]);

  const handleFormSubmit = useCallback(
    async (e: React.FormEvent<HTMLFormElement>) => {
      e.preventDefault();
      if (input.trim()) {
        await handleSubmit(input);
        setInput("");
        setTimeout(() => adjustTextareaHeight(), 0);
      }
    },
    [handleSubmit, input, adjustTextareaHeight]
  );

  const handleKeyDown = useCallback(
    async (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        if (input.trim()) {
          await handleSubmit(input);
          setInput("");
          setTimeout(() => adjustTextareaHeight(), 0);
        }
      }
    },
    [handleSubmit, input, adjustTextareaHeight]
  );

  useEffect(() => {
    const handleKeyPress = (e: KeyboardEvent) => {
      if (e.key === "/" && document.activeElement?.tagName !== "TEXTAREA") {
        e.preventDefault();
        textareaRef.current?.focus();
      }
    };

    window.addEventListener("keydown", handleKeyPress);
    return () => window.removeEventListener("keydown", handleKeyPress);
  }, []);

  return (
    <div className="p-2 max-w-4xl mx-auto w-full">
      <form
        onSubmit={handleFormSubmit}
        className="flex items-end gap-2 sm:gap-3 bg-gradient-to-r from-background to-muted/20 border border-border/50 rounded-xl sm:rounded-2xl p-2 sm:p-3 shadow-lg backdrop-blur-sm"
      >
        <div className="flex-1 relative min-w-0">
          <Textarea
            ref={textareaRef}
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="Ask about your transcripts..."
            className="resize-none border-none bg-transparent focus:ring-0 focus:outline-none overflow-y-auto placeholder:text-muted-foreground/60 text-sm sm:text-base"
            style={{ minHeight: "36px", maxHeight: "120px" }}
            disabled={isLoading}
            aria-label="Message input"
          />
          {!input && (
            <div className="absolute top-2 sm:top-3 right-2 sm:right-3 text-muted-foreground/40 pointer-events-none">
              <Sparkles className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
            </div>
          )}
        </div>
        <Button
          type="submit"
          size="icon"
          className="h-9 w-9 sm:h-10 sm:w-10 rounded-lg sm:rounded-xl bg-gradient-to-r from-primary to-primary/80 hover:from-primary/90 hover:to-primary/70 transition-all duration-200 shadow-md hover:shadow-lg hover:scale-105 flex-shrink-0"
          disabled={isLoading || selectedChatId === null || !input.trim()}
          aria-label="Send message"
        >
          {isLoading ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Send className="h-4 w-4" />
          )}
        </Button>
      </form>
      <div className="text-center mt-2 hidden sm:block">
        <p className="text-xs text-muted-foreground/60">
          Answers are generated by AI and may not be accurate. Use at your own
          discretion.
        </p>
      </div>
    </div>
  );
};

export default React.memo(MessageBar);