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