File size: 3,601 Bytes
d764c8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import MessageBubble from './MessageBubble';

const CAROUSEL_BREAKPOINT = 700;

const AdvisorCarousel = ({ messages = [], onReply, onExpand, onClick, onSearchReferences, userAvatarId, userAvatarOptions }) => {
  const [activeIndex, setActiveIndex] = useState(0);
  const [isCarouselMode, setIsCarouselMode] = useState(false);
  const containerRef = useRef(null);

  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;

    const observer = new ResizeObserver(entries => {
      const width = entries[0].contentRect.width;
      setIsCarouselMode(width < CAROUSEL_BREAKPOINT);
    });
    observer.observe(el);
    return () => observer.disconnect();
  }, []);

  useEffect(() => {
    setActiveIndex(0);
  }, [messages.length]);

  const goPrev = useCallback(() => {
    setActiveIndex(i => Math.max(0, i - 1));
  }, []);

  const goNext = useCallback(() => {
    setActiveIndex(i => Math.min(messages.length - 1, i + 1));
  }, [messages.length]);

  if (messages.length === 1) {
    return (
      <div className="single-response-wide">
        <MessageBubble
          message={messages[0]}
          onReply={onReply}
          onExpand={onExpand}
          onClick={onClick}
          onSearchReferences={onSearchReferences}
          showReplyButton={true}
          userAvatarId={userAvatarId}
          userAvatarOptions={userAvatarOptions}
        />
      </div>
    );
  }

  return (
    <div
      className={`advisor-carousel ${isCarouselMode ? 'carousel-mode' : 'grid-mode'}`}
      ref={containerRef}
    >
      {isCarouselMode && (
        <button
          className="carousel-arrow carousel-prev"
          onClick={goPrev}
          disabled={activeIndex === 0}
          aria-label="Previous advisor"
        >
          <ChevronLeft size={20} />
        </button>
      )}

      <div className="carousel-viewport">
        <div
          className="carousel-track"
          style={isCarouselMode ? { width: `${messages.length * 100}%`, transform: `translateX(-${activeIndex * (100 / messages.length)}%)` } : undefined}
        >
          {messages.map(message => (
            <div key={message.id} className="carousel-slide" style={isCarouselMode ? { width: `${100 / messages.length}%` } : undefined}>
              <MessageBubble
                message={message}
                onReply={onReply}
                onExpand={onExpand}
                onClick={onClick}
                onSearchReferences={onSearchReferences}
                showReplyButton={true}
                inlineAvatar={true}
                userAvatarId={userAvatarId}
                userAvatarOptions={userAvatarOptions}
              />
            </div>
          ))}
        </div>
      </div>

      {isCarouselMode && (
        <>
          <button
            className="carousel-arrow carousel-next"
            onClick={goNext}
            disabled={activeIndex === messages.length - 1}
            aria-label="Next advisor"
          >
            <ChevronRight size={20} />
          </button>

          <div className="carousel-dots">
            {messages.map((m, i) => (
              <button
                key={m.id}
                className={`carousel-dot ${i === activeIndex ? 'active' : ''}`}
                onClick={() => setActiveIndex(i)}
                aria-label={`Go to advisor ${i + 1}`}
              />
            ))}
          </div>
        </>
      )}
    </div>
  );
};

export default AdvisorCarousel;