File size: 2,970 Bytes
14ac924
 
 
 
773173b
 
 
 
14ac924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
798ecf9
14ac924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useState } from 'react'
import styles from './Sidebar.module.css'

function formatThreadLabel(thread) {
  // Show message preview if available, otherwise fall back to timestamp
  if (thread.preview) {
    return thread.preview
  }
  const date = new Date(thread.created_at)
  const today = new Date()
  const isToday = date.toDateString() === today.toDateString()
  return isToday
    ? date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
    : date.toLocaleDateString([], { month: 'short', day: 'numeric' })
}

export default function Sidebar({ threads, activeThreadId, loading, onSelectThread, onNewChat, onDeleteThread }) {
  const [collapsed, setCollapsed] = useState(false)

  return (
    <aside className={`${styles.sidebar} ${collapsed ? styles.collapsed : ''}`}>
      <div className={styles.top}>
        <button
          type="button"
          className={styles.toggle}
          onClick={() => setCollapsed((c) => !c)}
          aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
          title={collapsed ? 'Expand' : 'Collapse'}
        >
          <span className={`${styles.chevron} ${collapsed ? styles.chevronRight : ''}`} aria-hidden="true">
            ‹
          </span>
        </button>

        <button
          type="button"
          className={styles.newChat}
          onClick={onNewChat}
          disabled={loading}
          title="New conversation"
        >
          <span className={styles.newChatIcon} aria-hidden="true">+</span>
          <span className={styles.newChatLabel}>New chat</span>
        </button>
      </div>

      <nav className={styles.threadList} aria-label="Conversations">
        {threads.length === 0 && !collapsed && (
          <p className={styles.empty}>No conversations yet</p>
        )}
        {threads.map((t) => (
          <div
            key={t.thread_id}
            className={`${styles.threadItem} ${t.thread_id === activeThreadId ? styles.active : ''}`}
          >
            <button
              type="button"
              className={styles.threadButton}
              onClick={() => onSelectThread(t.thread_id)}
              disabled={loading}
              title={collapsed ? formatThreadLabel(t) : t.thread_id}
            >
              <span className={styles.threadIcon} aria-hidden="true">🗪</span>
              <span className={styles.threadLabel}>{formatThreadLabel(t)}</span>
            </button>
            {!collapsed && (
              <button
                type="button"
                className={styles.deleteThread}
                onClick={(e) => {
                  e.stopPropagation()
                  onDeleteThread(t.thread_id)
                }}
                disabled={loading}
                aria-label="Delete conversation"
                title="Delete conversation"
              >
                🗑
              </button>
            )}
          </div>
        ))}
      </nav>
    </aside>
  )
}