/ src / components / Table / ServicesTable.jsx
ServicesTable.jsx
  1  import { useRef, useState } from "react";
  2  import React from "react";
  3  import styles from "../Form/form.module.scss";
  4  import { useMediaQuery } from "react-responsive";
  5  
  6  const ServicesTable = ({
  7    rows,
  8    currencySymbol,
  9    onModifyTable,
 10    onAddInvoiceRow,
 11    onRemoveInvoiceRow,
 12    onTableData,
 13  }) => {
 14    const isMobile = useMediaQuery({ query: `(max-width: 760px)` });
 15    const rateRef = useRef([]);
 16    const quantityRef = useRef([]);
 17  
 18    const [weight, setWeight] = useState(0);
 19  
 20    const handleWeigthChange = (e) => {
 21      const newWeigth = parseFloat(e.target.value);
 22      setWeight(newWeigth);
 23    };
 24  
 25    const calculateAmount = (rate, qty) => {
 26      const amount = (
 27        parseFloat(rate ? rate : 0) * parseFloat(qty ? qty : 0)
 28      ).toFixed(2);
 29      return amount;
 30    };
 31  
 32  let updatedTableData;
 33    const tableRows = rows.map((item, index) => {
 34      updatedTableData = {
 35        productId: item? item.id: null,
 36        productName: item? item.description: null,
 37        productDescription: item? item.details : null,
 38        rate: item? item.rate: null,
 39        quantity: item? item.quantity : null,
 40        weight: weight,
 41      };
 42      return (
 43        <React.Fragment key={item.id}>
 44          {!isMobile && (
 45            <tr className={styles.item__row}>
 46              <td className={styles.item__row__actions}>
 47                <div className={styles.confirm__delete__button}>
 48                  <button
 49                    type="button"
 50                    title="Remove Item"
 51                    className={styles.btn__remove}
 52                    onClick={() => handleRemove(item.id)}
 53                  >
 54                    <svg
 55                      aria-hidden="true"
 56                      focusable="false"
 57                      data-prefix="fas"
 58                      data-icon="times"
 59                      className={styles.svg__close__icon}
 60                      role="img"
 61                      xmlns="http://www.w3.org/2000/svg"
 62                      viewBox="0 0 352 512"
 63                    >
 64                      <path
 65                        fill="currentColor"
 66                        d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
 67                      ></path>
 68                    </svg>
 69                  </button>
 70                </div>
 71              </td>
 72              <td className={styles.description}>
 73                <input
 74                  className={styles.input__default}
 75                  type="text"
 76                  name="description"
 77                  id={`description__${item.id}`}
 78                  key={`des-input_${item.id}`}
 79                  placeholder="Services Name"
 80                  maxLength={30}
 81                  onChange={(e) => handleChange(e, item)}
 82                  value={item.description || ""}
 83                />
 84                <textarea
 85                  name="details"
 86                  id={`details__${item.id}`}
 87                  key={`details-input_${item.id}`}
 88                  placeholder="Services Description..."
 89                  className={`${styles.input__default} ${styles.details}`}
 90                  onChange={(e) => handleChange(e, item)}
 91                  value={item.details || ""}
 92                ></textarea>
 93              </td>
 94              <td className={styles.rate}>
 95                <input
 96                  className={styles.input__default}
 97                  type="number"
 98                  name="rate"
 99                  id={`rate__${item.id}`}
100                  ref={(el) => (rateRef.current[index] = el)}
101                  placeholder="0.00"
102                  maxLength={20}
103                  key={`rate-input_${item.id}`}
104                  onChange={(e) => handleChange(e, item, index)}
105                  value={item.rate || ""}
106                />
107              </td>
108              <td className={styles.qty}>
109                <input
110                  className={styles.input__default}
111                  type="number"
112                  name="quantity"
113                  id={`quantity__${item.id}`}
114                  ref={(el) => (quantityRef.current[index] = el)}
115                  placeholder="0"
116                  maxLength={15}
117                  key={`qty-input_${item.id}`}
118                  onChange={(e) => handleChange(e, item, index)}
119                  value={item.quantity || ""}
120                />
121              </td>
122              <td className={styles.amount}>
123                <span>{currencySymbol} </span>
124                <span>{calculateAmount(item.rate, item.quantity, item.id)}</span>
125              </td>
126              {/* <td className={styles.tax}>Tax</td> */}
127            </tr>
128          )}
129  
130          {isMobile && (
131            <div className={styles.item__row}>
132              <div className={styles.description}>
133                <input
134                  className={styles.input__default}
135                  type="text"
136                  name="description"
137                  id={`description__${item.id}`}
138                  key={`des-input_${item.id}`}
139                  placeholder="Product Name"
140                  maxLength={20}
141                  onChange={(e) => handleChange(e, item)}
142                  value={item.description || ""}
143                />
144                <textarea
145                  name="details"
146                  id={`details__${item.id}`}
147                  key={`details-input_${item.id}`}
148                  placeholder="Services Description"
149                  className={`${styles.input__default} ${styles.mobile__details}`}
150                  onChange={(e) => handleChange(e, item)}
151                  value={item.details || ""}
152                ></textarea>
153              </div>
154              <div className={styles.input__group}>
155                <div className={styles.rate}>
156                  <input
157                    className={styles.input__default}
158                    type="number"
159                    name="rate"
160                    id={`rate__${item.id}`}
161                    ref={(el) => (rateRef.current[index] = el)}
162                    placeholder="price"
163                    maxLength={20}
164                    key={`rate-input_${item.id}`}
165                    onChange={(e) => handleChange(e, item, index)}
166                    value={item.rate || ""}
167                  />
168                </div>
169                <div className={styles.qty}>
170                  <input
171                    className={styles.input__default}
172                    type="number"
173                    name="quantity"
174                    id={`quantity__${item.id}`}
175                    ref={(el) => (quantityRef.current[index] = el)}
176                    placeholder="0"
177                    maxLength={15}
178                    key={`qty-input_${item.id}`}
179                    onChange={(e) => handleChange(e, item, index)}
180                    value={item.quantity || ""}
181                  />
182                </div>
183              </div>
184  
185              <div className={styles.item__row__actions__mobile}>
186                <div className={styles.confirm__delete__button}>
187                  <button
188                    type="button"
189                    title="Remove Item"
190                    className={styles.btn__remove}
191                    onClick={() => handleRemove(item.id)}
192                  >
193                    <svg
194                      aria-hidden="true"
195                      focusable="false"
196                      data-prefix="fas"
197                      data-icon="times"
198                      className={styles.svg__close__icon}
199                      role="img"
200                      xmlns="http://www.w3.org/2000/svg"
201                      viewBox="0 0 352 512"
202                    >
203                      <path
204                        fill="currentColor"
205                        d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
206                      ></path>
207                    </svg>
208                    <span className={styles.btn__text}>Delete</span>
209                  </button>
210                </div>
211                <div className={styles.amount}>
212                  <span>{currencySymbol} </span>
213                  <span>
214                    {calculateAmount(item.rate, item.quantity, item.id)}
215                  </span>
216                </div>
217              </div>
218            </div>
219          )}
220        </React.Fragment>
221      );
222    });
223  
224    const handleClick = () => {
225      onAddInvoiceRow();
226    };
227  
228    const handleRemove = (id) => {
229      onRemoveInvoiceRow(id);
230    };
231  
232    const handleChange = (e, item, index) => {
233      let amount;
234  
235      if (rateRef?.current[index] && quantityRef?.current[index]) {
236        let rate = Number(rateRef.current[index].value);
237        let quantity = Number(quantityRef.current[index].value);
238        amount = calculateAmount(rate, quantity);
239      }
240      onModifyTable(e, item.id, amount);
241      onTableData(updatedTableData);
242    };
243  
244    return (
245      <div className={styles.table__wrapper}>
246        {!isMobile && (
247          <table className={styles.table}>
248            <thead>
249              <tr className={styles.invoice__headers}>
250                <th className={styles.controls}>&nbsp;</th>
251                <th className={styles.description}>Description</th>
252                <th className={styles.rate}>Rate</th>
253                <th className={styles.qty}>Qty</th>
254                <th className={styles.amount}>Amount</th>
255                {/* <th className={styles.tax}>Tax</th> */}
256              </tr>
257            </thead>
258            <tbody className={styles.invoice__items}>
259              <>{tableRows}</>
260              <tr className={styles.item__row}>
261                <td className={styles.item__row__actions}>
262                  <button
263                    type="button"
264                    onClick={handleClick}
265                    className={`${styles.add__invoice__item} ${styles.btn__add}`}
266                  >
267                    <svg
268                      aria-hidden="true"
269                      focusable="false"
270                      data-prefix="fas"
271                      data-icon="plus"
272                      role="img"
273                      xmlns="http://www.w3.org/2000/svg"
274                      viewBox="0 0 448 512"
275                    >
276                      <path
277                        fill="#ffffff"
278                        d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
279                      ></path>
280                    </svg>
281                  </button>
282                </td>
283              </tr>
284            </tbody>
285          </table>
286        )}
287        {isMobile && (
288          <div className={styles.mobile__section}>
289            <>{tableRows}</>
290            <button
291              type="button"
292              onClick={handleClick}
293              className={`${styles.add__invoice__item} ${styles.btn__add}`}
294            >
295              <svg
296                aria-hidden="true"
297                focusable="false"
298                data-prefix="fas"
299                data-icon="plus"
300                role="img"
301                xmlns="http://www.w3.org/2000/svg"
302                viewBox="0 0 448 512"
303              >
304                <path
305                  fill="#ffffff"
306                  d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
307                ></path>
308              </svg>
309            </button>
310          </div>
311        )}
312      </div>
313    );
314  };
315  
316  export default ServicesTable;