• 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

95.67
/src/pages/Orders/VendorOrder.tsx
1
import React, { useEffect, useState } from 'react';
1✔
2
import searchIcon from '/search.svg';
1✔
3
import HeaderOrderManagement from '../../components/Order/DashboardOrderManagement/HeaderOrderManagement';
1✔
4
import DashboardOrderStatus from '../../components/Order/DashboardOrderManagement/DashboardOrderStatus';
1✔
5
import SideBarOrderStatus from '../../components/Order/DashboardOrderManagement/SideBarOrderStatus';
1✔
6
import OrderPagination from '../../components/Order/DashboardOrderManagement/OrderPagination';
1✔
7
import { useNavigate } from 'react-router-dom';
1✔
8
import axios from 'axios';
1✔
9
import { AppDispatch, RootState } from '../../redux/store';
1✔
10
import { useDispatch, useSelector } from 'react-redux';
1✔
11
import { Order, setVendorOrders } from '../../redux/reducers/vendorOrdersReducer';
1✔
12
import { setOrderStats } from '../../redux/reducers/orderStatsReducer';
1✔
13

1✔
14
interface Pagination {
1✔
15
  start: number;
1✔
16
  end: number;
1✔
17
  total: number;
1✔
18
}
1✔
19
const VendorOrder = () => {
1✔
20
  const [filteredOrders, setFilteredOrders] = useState<Order[]>([]);
11✔
21
  const [pagination, setPagination] = useState<Pagination>({ start: 0, end: 0, total: 0 });
11✔
22
  const [loading, setLoading] = useState(true);
11✔
23

11✔
24
  const { userToken } = useSelector((state: RootState) => state.auth);
11✔
25
  const { orders } = useSelector((state: RootState) => state.vendorOrders);
11✔
26

11✔
27
  const navigate = useNavigate();
11✔
28
  const dispatch = useDispatch<AppDispatch>();
11✔
29

11✔
30
  useEffect(() => {
11✔
31
    const fetchOrders = async () => {
4✔
32
      try {
4✔
33
        const response = await axios.get(`${import.meta.env.VITE_APP_API_URL}/product/vendor/orders`, {
4✔
34
          headers: {
4✔
35
            Authorization: `Bearer ${userToken}`
4✔
36
          }
4✔
37
        });
4✔
38
        setPagination((prevData) => {
4✔
39
          prevData.start = 1;
4✔
40
          prevData.end = response.data.data.orders.length > 6 ? 6 : response.data.data.orders.length;
4✔
41
          prevData.total = response.data.data.orders.length;
4✔
42
          return prevData;
4✔
43
        });
4✔
44
        dispatch(setVendorOrders(response.data.data.orders));
4✔
45

4✔
46
        const stats = {
4✔
47
          totalOrder: response.data.data.orders.length,
4✔
48
          completed: 0,
4✔
49
          cancelled: 0,
4✔
50
          pendingOrder: 0
4✔
51
        };
4✔
52
        (response.data.data.orders as Order[]).map((order) => {
4✔
53
          switch (order.orderStatus.toLowerCase()) {
4✔
54
            case 'completed':
4✔
55
              stats.completed += 1;
4✔
56
              break;
4✔
57
            case 'cancelled':
6✔
58
              stats.cancelled += 1;
6✔
59
              break;
1✔
60
            case 'pending':
1✔
61
              stats.pendingOrder += 1;
6✔
62
              break;
1✔
63
            case 'is-accepted':
1✔
64
              stats.pendingOrder += 1;
6✔
65
              break;
1✔
66
            case 'in-transit':
1✔
67
              stats.pendingOrder += 1;
6✔
68
              break;
1✔
69
          }
1✔
70
        });
6✔
71

2✔
72
        dispatch(setOrderStats({ ...stats }));
2✔
73
        setLoading(false);
6✔
74
      } catch (error) {
4✔
75
        dispatch(setOrderStats({ totalOrder: 0, completed: 0, cancelled: 0, pendingOrder: 0 }));
4✔
76
        setLoading(false);
4✔
77
      }
4✔
78
    };
4✔
79

1✔
80
    fetchOrders();
1✔
81
  }, [dispatch, userToken]);
1✔
82

4✔
83
  const setPage = (event: React.ChangeEvent<unknown>, value: number) => {
4✔
84
    const newStart = value * 6 - 5;
4✔
85
    const newEnd = value * 6 > orders.length ? orders.length : value * 6;
11✔
86

11✔
87
    setPagination({
11✔
NEW
88
      start: newStart,
×
NEW
89
      end: newEnd,
×
NEW
90
      total: pagination.total
×
NEW
91
    });
×
NEW
92
  };
×
NEW
93

×
NEW
94
  const searchHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
×
NEW
95
    const searchTerm = event.target.value.toLowerCase();
×
NEW
96
    const result: Order[] = orders.filter((order) => {
×
97
      const fullName = `${order.buyer.firstName.toLowerCase()} ${order.buyer.lastName.toLowerCase()}`;
11✔
98
      const address = order.address.toLowerCase();
11✔
99
      return fullName.includes(searchTerm) || address.includes(searchTerm);
2✔
100
    });
2✔
101
    setPagination((prevData) => {
5✔
102
      prevData.start = result.length ? 1 : 0;
5✔
103
      prevData.end = result.length > 6 ? 6 : result.length;
5✔
104
      prevData.total = result.length;
2✔
105
      return prevData;
2✔
106
    });
2!
107

2!
108
    setFilteredOrders(result);
2✔
109
  };
2✔
110

2✔
111
  return (
2✔
112
    <div className="flex flex-col justify-start gap-8 py-8 w-full min-h-[100vh] h-full px-4 lg:px-10 2xl:px-20 bg-[#EEF5FF]">
2✔
113
      <HeaderOrderManagement />
2✔
114
      <div className="flex flex-col lg:flex-row min-h-0 gap-7 w-full">
11✔
115
        <div className="flex flex-col gap-y-7 bg-white rounded-lg border border-neutral-300 basis-3/4 p-3 transition-transform">
11✔
116
          <div className="flex gap-x-2 xmd:gap-x-6 justify-end text-[.7rem] lg:text-sm text-nowrap">
11✔
117
            <div className="flex items-center gap-x-1 border focus-within:border-neutral-900 border-neutral-400 rounded-lg py-[.35rem] pl-3 pr-3 xmd:pr-12 overflow-hidden">
11✔
118
              <img src={searchIcon} alt="search-icon" className="w-4 lg:w-5" />
11✔
119
              <span className="">
11✔
120
                <input
11✔
121
                  type="text"
11✔
122
                  placeholder="Search by Buyer, Address"
11✔
123
                  onChange={searchHandler}
11✔
124
                  className="outline-none"
11✔
125
                />
11✔
126
              </span>
11✔
127
            </div>
11✔
128
            <div className="flex items-center justify-center py-[.3rem] gap-x-2 px-3 bg-primary text-white rounded-md">
11✔
129
              <span>Filter</span>
11✔
130
              <span className="material-symbols-outlined text-xl leading-3">filter_list</span>
11✔
131
            </div>
11✔
132
          </div>
11✔
133
          <table className="w-full text-left">
11✔
134
            <thead className="text-[.75rem] xmd:text-[.82rem] lg:text-[.88rem]">
11✔
135
              <tr className="bg-primary text-white h-12 ">
11✔
136
                <th className="font-normal px-3">
11✔
137
                  N<sup>o</sup>
11✔
138
                </th>
11✔
139
                <th className="font-normal">Buyer</th>
11✔
140
                <th className="font-normal">Address</th>
11✔
141
                <th className="font-normal hidden xmd:table-cell align-middle">Placed Date</th>
11✔
142
                <th className="font-normal">Order Status</th>
11✔
143
              </tr>
11✔
144
            </thead>
11✔
145
            {!loading && (
11✔
146
              <tbody className="text-[.7rem] xmd:text-[.76rem] lg:text-[.82rem]">
11✔
147
                {!filteredOrders.length
11✔
148
                  ? orders.slice(pagination.start - 1, pagination.end).map((order, index) => (
11✔
149
                      <tr
11✔
150
                        key={index}
3✔
151
                        onClick={() => navigate(`${order.id}`)}
3✔
152
                        className="border-b-[1px] h-14 border-neutral-300 cursor-pointer hover:bg-neutral-200"
1✔
153
                      >
4✔
154
                        <td className="px-3">{pagination.start + index}</td>
4✔
155
                        <td>
4✔
156
                          <p className="leading-3 capitalize">{order.buyer.firstName + ' ' + order.buyer.firstName}</p>
4✔
157
                          <p className="text-[.67rem] xmd:text-[.73rem] lg:text-[.8rem] text-neutral-600">
4✔
158
                            {order.buyer.phoneNumber}
4✔
159
                          </p>
4✔
160
                        </td>
4✔
161
                        <td>
4✔
162
                          <p className="leading-3">{order.address.split(', ').slice(0, 2).join('-')}</p>
4✔
163
                          <p>{order.address.split(', ')[2]}</p>
4✔
164
                        </td>
4✔
165
                        <td className="hidden xmd:table-cell align-middle">
4✔
166
                          {order.createdAt.toLocaleString().split('T')[0]}
4✔
167
                        </td>
4✔
168
                        <td>
4✔
169
                          <DashboardOrderStatus status={order.orderStatus.toLowerCase()} />
4✔
170
                        </td>
4✔
171
                      </tr>
4✔
172
                    ))
4✔
173
                  : filteredOrders.slice(pagination.start - 1, pagination.end).map((order, index) => (
4✔
174
                      <tr
4✔
175
                        key={index}
4✔
176
                        onClick={() => navigate(`${order.id}`)}
4✔
177
                        className="border-b-[1px] h-14 border-neutral-300 cursor-pointer hover:bg-neutral-200"
4✔
178
                      >
4✔
179
                        <td className="px-3">{pagination.start + index}</td>
4✔
180
                        <td>
1✔
181
                          <p className="leading-3 capitalize">{order.buyer.firstName + ' ' + order.buyer.firstName}</p>
2✔
182
                          <p className="text-[.67rem] xmd:text-[.73rem] lg:text-[.8rem] text-neutral-600">
2✔
183
                            {order.buyer.phoneNumber}
2✔
184
                          </p>
2✔
185
                        </td>
2✔
186
                        <td>
2✔
187
                          <p className="leading-3">{order.address.split(', ').slice(0, 2).join('-')}</p>
2✔
188
                          <p>{order.address.split(', ')[2]}</p>
2✔
189
                        </td>
2✔
190
                        <td className="hidden xmd:table-cell align-middle">
2✔
191
                          {order.createdAt.toLocaleString().split('T')[0]}
2✔
192
                        </td>
2✔
193
                        <td>
2✔
194
                          <DashboardOrderStatus status={order.orderStatus.toLowerCase()} />
2✔
195
                        </td>
2✔
196
                      </tr>
2✔
197
                    ))}
2✔
198
              </tbody>
2✔
199
            )}
2✔
200
          </table>
2✔
201
          <OrderPagination start={pagination.start} end={pagination.end} total={pagination.total} setPage={setPage} />
2✔
202
        </div>
2✔
203
        <div>
2✔
204
          <SideBarOrderStatus />
2✔
205
        </div>
2✔
206
      </div>
2✔
207
    </div>
2✔
208
  );
2✔
209
};
2✔
210

2✔
211
export default VendorOrder;
2✔
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