File size: 3,739 Bytes
9fc8a82
 
74cf3f1
1755110
 
 
 
 
f061065
9fc8a82
1755110
 
9fc8a82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1755110
 
f061065
 
 
 
74cf3f1
1755110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9fc8a82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1755110
 
 
 
 
 
 
 
 
 
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
import { useRef, useState } from 'react';
import { Wallet, LogOut, Loader2, Camera } from 'lucide-react';
import Logo from './Logo';

interface NavbarProps {
  user: any;
  onRechargeClick: () => void;
  onLogout: () => void;
  onLogoClick?: () => void;
  onAvatarUpload?: (newUrl: string) => void;
}

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';

export default function Navbar({ user, onRechargeClick, onLogout, onLogoClick, onAvatarUpload }: NavbarProps) {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);

  const handleAvatarClick = () => {
    if (fileInputRef.current && !uploading) {
      fileInputRef.current.click();
    }
  };

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    if (!file.type.startsWith('image/')) {
      alert('Please upload an image file.');
      return;
    }

    setUploading(true);
    const formData = new FormData();
    formData.append('file', file);

    const token = localStorage.getItem('quantiq_jwt');

    try {
      const response = await fetch(`${API_URL}/api/v1/users/avatar`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`
        },
        body: formData,
      });

      if (!response.ok) {
        throw new Error('Failed to upload avatar');
      }

      const data = await response.json();
      if (data.picture_url && onAvatarUpload) {
        onAvatarUpload(data.picture_url);
      }
    } catch (err) {
      console.error('Avatar upload error:', err);
      alert('Failed to upload avatar. Please try again.');
    } finally {
      setUploading(false);
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
    }
  };

  return (
    <header className="dashboard-header">
      <div 
        className={`header-left ${onLogoClick ? 'cursor-pointer hover:opacity-85 active:scale-[0.98]' : ''} transition-all`}
        onClick={onLogoClick}
      >
        <Logo size={32} />
        <span className="logo-text">QuantIQ</span>
      </div>
      
      <div className="header-right">
        {user && (
          <div className="credits-badge">
            <Wallet size={16} />
            <span>{user.credits} Credits</span>
            <button className="recharge-btn" onClick={onRechargeClick}>
              RECHARGE
            </button>
          </div>
        )}

        <div className="user-profile">
          <input 
            type="file" 
            ref={fileInputRef} 
            onChange={handleFileChange} 
            accept="image/*" 
            style={{ display: 'none' }} 
          />
          <div 
            className="avatar-upload-wrapper"
            onClick={handleAvatarClick}
            title="Click to upload custom avatar"
          >
            {user?.pictureUrl ? (
              <img src={user.pictureUrl} alt="Avatar" className="avatar" />
            ) : (
              <Camera size={14} style={{ color: 'var(--neon-cyan)' }} />
            )}
            
            <div className="avatar-hover-overlay">
              <Camera size={12} style={{ color: '#fff' }} />
            </div>

            {uploading && (
              <div className="avatar-upload-loading">
                <Loader2 size={12} className="animate-spin" style={{ color: 'var(--neon-cyan)' }} />
              </div>
            )}
          </div>
          <span className="profile-name">{user?.fullName || 'User'}</span>
        </div>

        <button className="logout-btn" onClick={onLogout} title="Log Out">
          <LogOut size={16} />
        </button>
      </div>
    </header>
  );
}