File size: 4,557 Bytes
b0c3c39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
133
134
135
136
137
138
139
140
141
import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { Node, Edge } from 'reactflow';
import styles from './SidePane.module.css';
import MindMapList from './MindMapList';
import axios from '../utils/axios';
import { MindMapData } from '../utils/jsonUtils';

// Icons with improved styling
const HomeIcon = () => (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">

    <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />

    <polyline points="9 22 9 12 15 12 15 22" />

  </svg>
);

const MindMapIcon = () => (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">

    <circle cx="12" cy="12" r="10" />

    <path d="M12 2v20M2 12h20" />

    <path d="M12 2a10 10 0 0 1 10 10M12 22a10 10 0 0 1-10-10" />

  </svg>
);

const LogoutIcon = () => (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">

    <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />

    <polyline points="16 17 21 12 16 7" />

    <line x1="21" y1="12" x2="9" y2="12" />

  </svg>
);

const ChevronIcon = ({ isCollapsed }: { isCollapsed: boolean }) => (
  <svg

    width="16"

    height="16"

    viewBox="0 0 24 24"

    fill="none"

    stroke="currentColor"

    strokeWidth="2"

    strokeLinecap="round"

    strokeLinejoin="round"

    style={{

      transform: isCollapsed ? 'rotate(180deg)' : 'rotate(0deg)',

      transition: 'transform 0.3s ease',

    }}

  >

    <polyline points="15 18 9 12 15 6" />

  </svg>
);

interface SidePaneProps {
  onSelectMindMap: (mindMap: MindMapData) => void;
  onNewMindMap: () => void;
  isCollapsed: boolean;
  setIsCollapsed: (collapsed: boolean) => void;
  onDeleteMindMap: (id: string) => void;
}

const SidePane: React.FC<SidePaneProps> = ({ onSelectMindMap, onNewMindMap, isCollapsed, setIsCollapsed, onDeleteMindMap }) => {
  const navigate = useNavigate();
  const location = useLocation();
  const isEditor = location.pathname === '/editor';

  const handleLogout = async () => {
    try {
      await axios.post('/logout');
    } catch (error) {
      // Ignore error, proceed to clear token and redirect
    }
    localStorage.removeItem('token');
    navigate('/');
  };

  const handleNavigation = (path: string) => (e: React.MouseEvent) => {
    e.preventDefault();
    try {
      navigate(path);
    } catch (error) {
      console.error('Navigation error:', error);
      // Fallback to window.location if navigation fails
      window.location.href = path;
    }
  };

  return (
    <div className={`${styles.sidePane} ${isCollapsed ? styles.collapsed : styles.expanded}`}>

      <button

        className={styles.toggleButton}

        onClick={() => setIsCollapsed(!isCollapsed)}

        aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}

      >

        <ChevronIcon isCollapsed={isCollapsed} />

      </button>



      <div className={styles.menuItems}>

        <a

          href="/"

          className={`${styles.menuItem} ${location.pathname === '/' ? styles.active : ''}`}

          onClick={handleNavigation('/')}

        >

          <span className={styles.icon}>

            <HomeIcon />

          </span>

          <span className={styles.label}>Home</span>

        </a>



        <a

          href="/editor"

          className={`${styles.menuItem} ${location.pathname === '/editor' ? styles.active : ''}`}

          onClick={handleNavigation('/editor')}

        >

          <span className={styles.icon}>

            <MindMapIcon />

          </span>

          <span className={styles.label}>Mind Map</span>

        </a>



        {isEditor && (

          <MindMapList

            isCollapsed={isCollapsed}

            onSelectMindMap={onSelectMindMap}

            onNewMindMap={onNewMindMap}

            onDeleteMindMap={onDeleteMindMap}

          />

        )}

      </div>



      <div className={`${styles.logoutButton} ${isCollapsed ? styles.collapsed : ''}`}>

        <button onClick={handleLogout} aria-label="Logout">

          <span className={styles.icon}>

            <LogoutIcon />

          </span>

          <span className={styles.label}>Logout</span>

        </button>

      </div>

    </div>
  );
};

export default SidePane;