• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atlp-rwanda / knights-ecomm-fe / 10060387859

23 Jul 2024 10:55AM UTC coverage: 90.757% (+0.09%) from 90.671%
10060387859

push

github

web-flow
Merge pull request #73 from atlp-rwanda/ft-order-management

#68 Implement vendor and admin order management feature

1079 of 1360 branches covered (79.34%)

Branch coverage included in aggregate %.

1519 of 1727 new or added lines in 21 files covered. (87.96%)

3 existing lines in 2 files now uncovered.

11332 of 12315 relevant lines covered (92.02%)

12.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/src/components/Dashboard/DashboardNavbar/DashboardNavbar.tsx
1
import React, { useState, useEffect } from 'react';
1✔
2
import { NavLink, useNavigate } from 'react-router-dom';
1✔
3
import { useDispatch, useSelector } from 'react-redux';
1✔
4
import { jwtDecode } from 'jwt-decode';
1✔
5
import notificationIcon from '/notification.svg';
1✔
6
import searchIcon from '/search.svg';
1✔
7
import { AlignJustify } from 'lucide-react';
1✔
8
import { setOpenNotification } from '../../../redux/reducers/notification';
1✔
9
import NotificationLayout from '../../Notification/NotificationLayout';
1✔
10
import { AppDispatch, RootState } from '../../../redux/store';
1✔
11
import { DecodedToken } from '../../../pages/Authentication/Login';
1✔
12
import { useJwt } from 'react-jwt';
1✔
13

1✔
14
interface DashboardNavBarProps {
1✔
15
  setOpenNav: (open: boolean) => void;
1✔
16
}
1✔
17

1✔
18
interface TokenPayload {
1✔
19
  email: string;
1✔
20
  name: string;
1✔
21
  userType: string;
1✔
22
  exp: number;
1✔
23
  firstName: string;
1✔
24
}
1✔
25

1✔
26
const DashboardNavbar: React.FC<DashboardNavBarProps> = ({ setOpenNav }) => {
1✔
27
  const [searchTerm, setSearchTerm] = useState('');
22✔
28
  const [currentDateTime, setCurrentDateTime] = useState('');
22✔
29
  const [userName, setUserName] = useState('');
22✔
30
  const navigate = useNavigate();
22✔
31
  const { openNotification, unreadNotifications } = useSelector((state: RootState) => state.notification);
22✔
32
  const dispatch = useDispatch<AppDispatch>();
22✔
33

22✔
34
  const { userToken } = useSelector((state: RootState) => state.auth);
22✔
35
  const { decodedToken } = useJwt<DecodedToken>(userToken);
22✔
36

22✔
37
  const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
22✔
38
    setSearchTerm(event.target.value);
22✔
39
  };
22✔
40

1✔
41
  const handleNotificationPopup = () => {
1✔
42
    dispatch(setOpenNotification(!openNotification));
22✔
43
  };
22✔
44

1✔
45
  useEffect(() => {
1✔
46
    const updateDateTime = () => {
22✔
47
      const now = new Date();
22✔
48
      const options: Intl.DateTimeFormatOptions = {
8✔
49
        day: 'numeric',
8✔
50
        month: 'long',
8✔
51
        year: 'numeric',
8✔
52
        hour: 'numeric',
8✔
53
        minute: 'numeric',
8✔
54
        hour12: true,
8✔
55
        timeZone: 'Etc/GMT-2',
8✔
56
        timeZoneName: 'short'
8✔
57
      };
8✔
58
      const formattedDateTime = new Intl.DateTimeFormat('en-GB', options).format(now);
8✔
59
      setCurrentDateTime(formattedDateTime);
8✔
60
    };
8✔
61

8✔
62
    updateDateTime();
8✔
63
    const intervalId = setInterval(updateDateTime, 60000);
8✔
64

8✔
65
    return () => clearInterval(intervalId);
8✔
66
  }, []);
8✔
67

8✔
68
  useEffect(() => {
22✔
69
    const tokenString = localStorage.getItem('userToken');
22✔
70
    if (!tokenString) {
22✔
71
      navigate('/login');
12✔
72
      return;
12✔
73
    }
8✔
74

8✔
75
    try {
8✔
76
      const decodedToken = jwtDecode<TokenPayload>(tokenString);
4✔
77
      //send name in token
4✔
78
      setUserName(decodedToken.firstName);
4✔
79
    } catch (error) {
4✔
80
      console.error('Failed to decode token:', error);
4✔
81
      navigate('/login');
10!
82
    }
×
83
  }, [navigate]);
×
84

×
85
  return (
22✔
86
    <div
22✔
87
      className="flex flex-col-reverse md:flex-row md:justify-between md:items-center gap-1 md:gap-0 items-end px-4 lg:px-10 2xl:px-20 py-1 md:py-4 border-b-[1px] border-neutral-300 text-black"
22✔
88
      data-testid="navbar"
22✔
89
    >
22✔
90
      <div className="flex flex-col items-end md:items-start">
22✔
91
        <p className="font-semibold leading-5 capitalize text-sm lg:text-[.95rem]">Welcome, {userName}</p>
22✔
92
        <p className="text-[#7c7c7c] text-[.65rem] lg:text-[.8rem]">{currentDateTime}</p>
22✔
93
      </div>
22✔
94
      <NotificationLayout />
22✔
95
      <div className="flex min-w-full md:min-w-5 flex-col md:flex-row gap-4">
22✔
96
        <div className="flex justify-between">
22✔
97
          <NavLink
22✔
98
            to={'/' + decodedToken?.role.toLowerCase() + '/dashboard'}
22✔
99
            className="md:hidden text-2xl font-bold text-primary py-2"
22✔
100
          >
22✔
101
            Knights
22✔
102
          </NavLink>
22!
103
          <div className="flex gap-4 items-center">
22✔
104
            <button onClick={handleNotificationPopup} className="relative px-5 py-1 md:border-r border-neutral-300">
22✔
105
              <img src={notificationIcon} alt="Notification" className="w-5" />
22✔
106
              {unreadNotifications > 0 && (
22✔
107
                <span className="absolute min-w-5 min-h-4 top-1 right-[27px] mt-[-10px] mr-[-15px] bg-orange text-white text-[.7rem] font-semibold flex items-center justify-center rounded-full leading-none p-1">
22✔
108
                  {unreadNotifications}
22✔
109
                </span>
22✔
110
              )}
22✔
111
            </button>
22✔
112
            <button onClick={() => setOpenNav(true)} className="md:hidden" name="AlignJustify">
22✔
113
              <AlignJustify />
22!
NEW
114
            </button>
×
NEW
115
          </div>
×
116
        </div>
×
117
        <div className="hidden md:flex px-4 py-1 rounded-md border border-[#d1d1d1] gap-2">
22✔
118
          <img src={searchIcon} alt="Search" className="w-4 lg:w-5" />
22✔
119
          <input
22✔
120
            type="text"
22✔
121
            className="bg-white text-[.8rem] lg:text-[.9rem] w-[140px] lg:w-[200px] outline-none"
22✔
122
            placeholder="Search..."
22✔
123
            value={searchTerm}
22✔
124
            onChange={handleSearchChange}
22✔
125
          />
22✔
126
        </div>
22✔
127
      </div>
22✔
128
    </div>
22✔
129
  );
22✔
130
};
22✔
131

22✔
132
export default DashboardNavbar;
22✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc