File size: 9,957 Bytes
308a91d
 
 
17178b7
72c5e3a
308a91d
 
 
 
 
 
 
454ca1f
17178b7
3083f4d
 
3d08544
3083f4d
 
 
 
 
3d08544
 
 
 
 
 
 
3083f4d
 
 
17178b7
 
 
 
 
 
 
 
308a91d
 
 
 
 
 
 
 
b9857f0
308a91d
7607c2e
 
308a91d
 
baf13ff
308a91d
 
 
 
3083f4d
 
 
 
 
 
 
 
308a91d
 
 
 
 
7607c2e
308a91d
 
 
 
 
b9857f0
 
7607c2e
308a91d
7607c2e
308a91d
 
 
 
 
 
7607c2e
308a91d
7607c2e
 
 
308a91d
 
407ebaa
 
16e8fe5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6efafa2
 
 
 
 
 
 
 
 
 
 
 
 
 
16e8fe5
407ebaa
 
c83c8f8
 
17178b7
c83c8f8
7607c2e
c83c8f8
7607c2e
c83c8f8
7607c2e
c83c8f8
 
7607c2e
c83c8f8
 
 
 
 
 
17178b7
c83c8f8
7607c2e
c83c8f8
7607c2e
c83c8f8
7607c2e
c83c8f8
 
7607c2e
c83c8f8
 
 
 
308a91d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import { useState, useRef, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import useAuthStore from '../store/useAuthStore';
import { getCompanySlug } from '../utils/slug';
import api from '../api/axios';

export default function Navbar() {
  const { user, logout } = useAuthStore();
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  const navigate = useNavigate();
  const location = useLocation();
  const isOwner = user?.role === 'owner';
  const slug = getCompanySlug(user?.company_name);
  const [balance, setBalance] = useState(null);

  const loadWallet = () => {
    if (user?.role === 'owner' || user?.role === 'kasir') {
      api.get('/api/companies/me').then(res => {
        setBalance(res.data.wallet_balance);
      }).catch(e => console.error("Gagal load wallet", e));
    }
  };

  useEffect(() => {
    loadWallet();
    const handleWalletUpdate = () => loadWallet();
    window.addEventListener('refresh_wallet', handleWalletUpdate);
    return () => window.removeEventListener('refresh_wallet', handleWalletUpdate);
  }, [user]);

  const formatRp = (num) => 'Rp ' + (num || 0).toLocaleString('id-ID');

  const getNavPath = (p) => {
    if (user?.role === 'super_admin') return p;
    return `/${slug}${p}`;
  };

  const isOnPOSArea = location.pathname.includes('/pos') || location.pathname.includes('/kasir');
  const isOnReportPage = location.pathname.endsWith('/kasir/report');

  useEffect(() => {
    const fn = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', fn);
    return () => document.removeEventListener('mousedown', fn);
  }, []);

  return (
    <header className="navbar-header" style={{
      position: 'sticky', top: 0, zIndex: 30,
      background: 'rgba(240,245,248,0.85)', backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)',
      borderBottom: '1px solid rgba(8,45,67,0.06)',
      display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '16px 32px',
    }}>
      <div className="nav-date" style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'rgba(8,45,67,0.45)', fontSize: '14px', fontWeight: 500 }}>
        <span className="material-symbols-outlined" style={{ fontSize: '18px' }}>calendar_today</span>
        {new Date().toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })}
      </div>

      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: '16px' }} ref={ref}>
        {balance !== null && (
          <div style={{ background: 'rgba(14, 165, 233, 0.1)', padding: '6px 12px', borderRadius: '8px', color: '#0ea5e9', fontSize: '13px', fontWeight: 700, display: 'flex', alignItems: 'center', gap: '6px' }} title="Sisa Saldo Wallet">
            <span className="material-symbols-outlined" style={{ fontSize: '16px' }}>account_balance_wallet</span>
            {formatRp(balance)}
          </div>
        )}

        <button onClick={() => setOpen(!open)} style={{
          display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px',
          borderRadius: '12px', border: 'none', cursor: 'pointer', background: 'transparent',
          transition: 'background 0.2s',
        }}
          onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.06)'}
          onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
        >
          <div className="bg-ember" style={{ width: '36px', height: '36px', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white' }}>
            <span className="material-symbols-outlined" style={{ fontSize: '18px' }}>person</span>
          </div>
          <div className="navbar-profile-text" style={{ textAlign: 'left' }}>
            <p className="navbar-profile-name" style={{ fontSize: '14px', fontWeight: 700, color: '#0a1f2e', lineHeight: 1.2, whiteSpace: 'nowrap' }}>{user?.name}</p>
            <p style={{ fontSize: '11px', color: 'rgba(8,45,67,0.45)', textTransform: 'capitalize' }}>{user?.role}</p>
          </div>
          <span className="material-symbols-outlined" style={{ fontSize: '18px', color: 'rgba(8,45,67,0.4)', transition: 'transform 0.2s', transform: open ? 'rotate(180deg)' : 'none' }}>expand_more</span>
        </button>

        {open && (
          <div className="animate-fade-in" style={{
            position: 'absolute', right: 0, top: '100%', marginTop: '8px', width: '220px',
            background: '#ffffff', borderRadius: '16px', overflow: 'hidden',
            border: '1px solid rgba(8,45,67,0.06)', boxShadow: '0 12px 40px rgba(8,45,67,0.12)',
          }}>
            <div style={{ padding: '12px 16px', borderBottom: '1px solid rgba(8,45,67,0.06)' }}>
              <p style={{ fontSize: '14px', fontWeight: 700, color: '#0a1f2e' }}>{user?.name}</p>
              <p style={{ fontSize: '12px', color: 'rgba(8,45,67,0.45)' }}>{user?.email}</p>
            </div>

            {/* Laporan Harian - muncul di halaman kasir/POS area */}
            {isOnPOSArea && (
              <>
                <button onClick={() => { navigate(isOnReportPage ? getNavPath('/pos') : getNavPath('/kasir/report')); setOpen(false); }} style={{
                  width: '100%', padding: '12px 16px', textAlign: 'left', fontSize: '14px', fontWeight: 500,
                  color: '#0a1f2e', display: 'flex', alignItems: 'center', gap: '8px',
                  border: 'none', cursor: 'pointer', background: 'transparent', transition: 'background 0.2s',
                  borderBottom: '1px solid rgba(8,45,67,0.06)',
                }}
                  onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.04)'}
                  onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
                >
                  <span className="material-symbols-outlined" style={{ fontSize: '18px', color: '#082D43' }}>
                    {isOnReportPage ? 'point_of_sale' : 'bar_chart'}
                  </span>
                  {isOnReportPage ? 'Kembali ke Kasir' : 'Laporan Harian'}
                </button>

                {user?.company_settings?.enable_member !== false && (
                  <button onClick={() => { navigate(getNavPath('/admin/members')); setOpen(false); }} style={{
                    width: '100%', padding: '12px 16px', textAlign: 'left', fontSize: '14px', fontWeight: 500,
                    color: '#0a1f2e', display: 'flex', alignItems: 'center', gap: '8px',
                    border: 'none', cursor: 'pointer', background: 'transparent', transition: 'background 0.2s',
                    borderBottom: '1px solid rgba(8,45,67,0.06)',
                  }}
                    onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.04)'}
                    onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
                  >
                    <span className="material-symbols-outlined" style={{ fontSize: '18px', color: '#082D43' }}>group</span>
                    Member
                  </button>
                )}
              </>
            )}

            {/* Buka Kasir - hanya owner di luar POS area */}
            {isOwner && !isOnPOSArea && (
              <button onClick={() => { navigate(getNavPath('/pos')); setOpen(false); }} style={{
                width: '100%', padding: '12px 16px', textAlign: 'left', fontSize: '14px', fontWeight: 500,
                color: '#0a1f2e', display: 'flex', alignItems: 'center', gap: '8px',
                border: 'none', cursor: 'pointer', background: 'transparent', transition: 'background 0.2s',
                borderBottom: '1px solid rgba(8,45,67,0.06)',
              }}
                onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.04)'}
                onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
              >
                <span className="material-symbols-outlined" style={{ fontSize: '18px', color: '#082D43' }}>point_of_sale</span>
                Buka Kasir (POS)
              </button>
            )}

            {/* Kembali ke Dashboard - hanya owner di POS area */}
            {isOwner && isOnPOSArea && (
              <button onClick={() => { navigate(getNavPath('/dashboard')); setOpen(false); }} style={{
                width: '100%', padding: '12px 16px', textAlign: 'left', fontSize: '14px', fontWeight: 500,
                color: '#0a1f2e', display: 'flex', alignItems: 'center', gap: '8px',
                border: 'none', cursor: 'pointer', background: 'transparent', transition: 'background 0.2s',
                borderBottom: '1px solid rgba(8,45,67,0.06)',
              }}
                onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.04)'}
                onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
              >
                <span className="material-symbols-outlined" style={{ fontSize: '18px', color: '#082D43' }}>dashboard</span>
                Kembali ke Dashboard
              </button>
            )}


            <button onClick={logout} style={{
              width: '100%', padding: '12px 16px', textAlign: 'left', fontSize: '14px', fontWeight: 500,
              color: '#b31b25', display: 'flex', alignItems: 'center', gap: '8px',
              border: 'none', cursor: 'pointer', background: 'transparent', transition: 'background 0.2s',
            }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(179,27,37,0.05)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
            >
              <span className="material-symbols-outlined" style={{ fontSize: '18px' }}>logout</span>
              Keluar
            </button>
          </div>
        )}
      </div>
    </header>
  );
}