@zauru-sdk/hooks 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,97 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { ExitSvg } from "@zauru-sdk/icons";
4
+ import { createRoot } from "react-dom/client";
5
+ import { AnimatePresence, motion } from "framer-motion";
6
+ const Alert = ({ type, title, description, onClose }) => {
7
+ const [, setLifetime] = useState(4000);
8
+ const [progress, setProgress] = useState(0);
9
+ const intervalRef = useRef(null);
10
+ const getColor = () => {
11
+ switch (type) {
12
+ case "success":
13
+ return "bg-green-100 text-green-800";
14
+ case "error":
15
+ return "bg-red-100 text-red-800";
16
+ case "info":
17
+ return "bg-blue-100 text-blue-800";
18
+ case "warning":
19
+ return "bg-yellow-100 text-yellow-800";
20
+ default:
21
+ return "bg-gray-100 text-gray-800";
22
+ }
23
+ };
24
+ useEffect(() => {
25
+ const startTimer = () => {
26
+ intervalRef.current = setInterval(() => {
27
+ setLifetime((lifetime) => {
28
+ if (lifetime <= 0) {
29
+ onClose && onClose();
30
+ clearInterval(intervalRef.current);
31
+ return 0;
32
+ }
33
+ else {
34
+ setProgress((4000 - lifetime) / 4000);
35
+ return lifetime - 50;
36
+ }
37
+ });
38
+ }, 50);
39
+ };
40
+ const pauseTimer = () => {
41
+ clearInterval(intervalRef.current);
42
+ };
43
+ startTimer();
44
+ return () => {
45
+ pauseTimer();
46
+ };
47
+ }, [onClose]);
48
+ return (_jsxs(motion.div, { initial: { y: -50, opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: -50, opacity: 0 }, className: `fixed top-0 right-0 w-80 mt-10 mr-10 rounded-md shadow-lg ${getColor()} p-4 transition-transform duration-300`, style: {
49
+ zIndex: 1000,
50
+ transform: `translateY(calc(var(--alert-offset, 0)))`,
51
+ }, onMouseEnter: () => clearInterval(intervalRef.current), onMouseLeave: () => {
52
+ intervalRef.current = setInterval(() => {
53
+ setLifetime((lifetime) => {
54
+ if (lifetime <= 0) {
55
+ onClose && onClose();
56
+ clearInterval(intervalRef.current);
57
+ return 0;
58
+ }
59
+ else {
60
+ setProgress((4000 - lifetime) / 4000);
61
+ return lifetime - 50;
62
+ }
63
+ });
64
+ }, 50);
65
+ }, children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "font-semibold", children: title }), _jsx("button", { className: "text-gray-400 hover:text-gray-500 focus:outline-none focus:text-gray-500 transition duration-150 ease-in-out", onClick: () => {
66
+ setLifetime(0);
67
+ onClose && onClose();
68
+ }, children: _jsx(ExitSvg, {}) })] }), _jsx("div", { className: "mt-2", children: _jsx("p", { className: "text-sm overflow-wrap break-words", children: description }) }), _jsx("div", { className: "relative h-1 mt-4 bg-gray-200 rounded", children: _jsx("div", { className: `absolute left-0 top-0 h-full ${getColor()} rounded`, style: { width: `${progress * 100}%` } }) })] }));
69
+ };
70
+ let activeAlerts = [];
71
+ export const showAlert = (alertProps) => {
72
+ if (typeof document === "undefined") {
73
+ return;
74
+ }
75
+ const container = document.createElement("div");
76
+ document.body.appendChild(container);
77
+ const onClose = () => {
78
+ root.unmount();
79
+ container.remove();
80
+ activeAlerts = activeAlerts.filter((alert) => alert !== container);
81
+ updateAlertOffsets();
82
+ };
83
+ const asyncOnClose = () => {
84
+ setTimeout(() => {
85
+ onClose();
86
+ }, 0);
87
+ };
88
+ activeAlerts.push(container);
89
+ updateAlertOffsets();
90
+ const root = createRoot(container);
91
+ root.render(_jsx(AnimatePresence, { children: _jsx(Alert, { ...alertProps, onClose: asyncOnClose }) }));
92
+ };
93
+ const updateAlertOffsets = () => {
94
+ activeAlerts.forEach((alertContainer, index) => {
95
+ alertContainer.style.setProperty("--alert-offset", `${index * 100}px`);
96
+ });
97
+ };
@@ -0,0 +1 @@
1
+ export * from "./Alert";
@@ -0,0 +1 @@
1
+ export * from "./Alert";
@@ -0,0 +1,10 @@
1
+ export * from "./components";
2
+ export * from "./alerts";
3
+ export * from "./automaticNumbers";
4
+ export * from "./catalogs";
5
+ export * from "./onlineStatus";
6
+ export * from "./profiles";
7
+ export * from "./receptions";
8
+ export * from "./session";
9
+ export * from "./templates";
10
+ export * from "./useWindowDimensions";
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from "./components";
2
+ export * from "./alerts";
3
+ export * from "./automaticNumbers";
4
+ export * from "./catalogs";
5
+ export * from "./onlineStatus";
6
+ export * from "./profiles";
7
+ export * from "./receptions";
8
+ export * from "./session";
9
+ export * from "./templates";
10
+ export * from "./useWindowDimensions";
@@ -0,0 +1 @@
1
+ export declare const useIsOnline: () => boolean;
@@ -0,0 +1,27 @@
1
+ import { useState, useEffect } from "react";
2
+ // Hook personalizado para verificar el estado de conexión
3
+ export const useIsOnline = () => {
4
+ // Verificar si estamos en el entorno del servidor o del cliente
5
+ const isServer = typeof window === "undefined";
6
+ // Estado local para almacenar si la aplicación está en línea o no
7
+ const [isOnline, setIsOnline] = useState(!isServer && navigator.onLine);
8
+ // Función para manejar el cambio de estado de conexión
9
+ const handleConnectionChange = () => {
10
+ setIsOnline(navigator.onLine);
11
+ };
12
+ useEffect(() => {
13
+ if (isServer) {
14
+ // Si estamos en el servidor, no añadir los event listeners
15
+ return;
16
+ }
17
+ // Añadir event listeners
18
+ window.addEventListener("online", handleConnectionChange);
19
+ window.addEventListener("offline", handleConnectionChange);
20
+ // Limpiar event listeners al desmontar el componente
21
+ return () => {
22
+ window.removeEventListener("online", handleConnectionChange);
23
+ window.removeEventListener("offline", handleConnectionChange);
24
+ };
25
+ }, [isServer]);
26
+ return isOnline;
27
+ };
@@ -0,0 +1,17 @@
1
+ import type { AgencyGraphQL, EmployeeGraphQL, OauthProfile, ProfileResponse } from "@zauru-sdk/types";
2
+ export declare const useGetAgencyProfile: () => {
3
+ loading: boolean;
4
+ data: AgencyGraphQL;
5
+ };
6
+ export declare const useGetUserProfile: () => {
7
+ loading: boolean;
8
+ data: ProfileResponse;
9
+ };
10
+ export declare const useGetOauthProfile: () => {
11
+ loading: boolean;
12
+ data: OauthProfile;
13
+ };
14
+ export declare const useGetEmployeeProfile: () => {
15
+ loading: boolean;
16
+ data: EmployeeGraphQL;
17
+ };
@@ -0,0 +1,57 @@
1
+ import { useFetcher } from "@remix-run/react";
2
+ import { useEffect, useState } from "react";
3
+ import { showAlert } from "src";
4
+ import { profileFetchStart, profileFetchSuccess, useAppDispatch, useAppSelector, } from "@zauru-sdk/redux";
5
+ const useGetProfile = (PROFILE_NAME) => {
6
+ const fetcher = useFetcher();
7
+ const dispatch = useAppDispatch();
8
+ const profileData = useAppSelector((state) => state.profiles[PROFILE_NAME]);
9
+ const [data, setData] = useState({
10
+ data: Object.keys(profileData?.data)?.length
11
+ ? profileData?.data
12
+ : {},
13
+ loading: profileData?.loading,
14
+ });
15
+ useEffect(() => {
16
+ if (fetcher.data?.title) {
17
+ showAlert({
18
+ description: fetcher.data?.description?.toString(),
19
+ title: fetcher.data?.title?.toString(),
20
+ type: fetcher.data?.type?.toString(),
21
+ });
22
+ }
23
+ }, [fetcher.data]);
24
+ useEffect(() => {
25
+ if (fetcher.state === "idle" && fetcher.data != null) {
26
+ const receivedData = fetcher.data;
27
+ if (receivedData) {
28
+ setData({ data: receivedData[PROFILE_NAME], loading: false });
29
+ dispatch(profileFetchSuccess({
30
+ name: PROFILE_NAME,
31
+ data: receivedData[PROFILE_NAME],
32
+ }));
33
+ }
34
+ }
35
+ }, [fetcher, dispatch, PROFILE_NAME]);
36
+ useEffect(() => {
37
+ if (Object.keys(profileData?.data).length <= 0) {
38
+ try {
39
+ setData({ ...data, loading: true });
40
+ dispatch(profileFetchStart(PROFILE_NAME));
41
+ fetcher.load(`/api/profiles?profile=${PROFILE_NAME}`);
42
+ }
43
+ catch (ex) {
44
+ showAlert({
45
+ type: "error",
46
+ title: `Ocurrió un error al cargar el perfil: ${PROFILE_NAME}.`,
47
+ description: "Error: " + ex,
48
+ });
49
+ }
50
+ }
51
+ }, []);
52
+ return data;
53
+ };
54
+ export const useGetAgencyProfile = () => useGetProfile("agencyProfile");
55
+ export const useGetUserProfile = () => useGetProfile("userProfile");
56
+ export const useGetOauthProfile = () => useGetProfile("oauthProfile");
57
+ export const useGetEmployeeProfile = () => useGetProfile("employeeProfile");
@@ -0,0 +1,102 @@
1
+ import { ItemAssociatedLots, ItemGraphQL, NewPurchaseOrderResponse, PayeeGraphQL, PurchaseOrderGeneralInfo, PurchaseOrderGraphQL, QueueFormReceptionWebAppTable, RejectionWebAppTableObject, WebAppRowGraphQL, GenericDynamicTableColumn } from "@zauru-sdk/types";
2
+ type ConfigProps = {
3
+ online?: boolean;
4
+ wheres?: string[];
5
+ };
6
+ export declare const useGetProcesses: (config?: ConfigProps) => {
7
+ loading: boolean;
8
+ data: WebAppRowGraphQL<QueueFormReceptionWebAppTable>[];
9
+ };
10
+ export declare const useGetPOReceptions: (config?: ConfigProps) => {
11
+ loading: boolean;
12
+ data: PurchaseOrderGraphQL[];
13
+ };
14
+ export declare const useGetBasketLots: () => {
15
+ loading: boolean;
16
+ data: ItemAssociatedLots;
17
+ };
18
+ export declare const useGetRejectionInfo: () => {
19
+ loading: boolean;
20
+ data: RejectionWebAppTableObject;
21
+ };
22
+ export declare const useGetNewPurchaseOrderInfo: () => {
23
+ loading: boolean;
24
+ data: NewPurchaseOrderResponse;
25
+ };
26
+ export declare const useGetPurchaseOrderGeneralInfo: () => {
27
+ loading: boolean;
28
+ data: PurchaseOrderGeneralInfo;
29
+ };
30
+ /**
31
+ * ---------------- Hooks personalizados
32
+ */
33
+ type FormInput = {
34
+ idNumberInput: string;
35
+ rType: string;
36
+ vendor: string;
37
+ porcentajeRechazo: string;
38
+ [key: string]: string | undefined;
39
+ };
40
+ type PesadaBody = {
41
+ id: number;
42
+ baskets: number;
43
+ totalWeight: number;
44
+ discount: number;
45
+ netWeight: string;
46
+ weightByBasket: string;
47
+ probableUtilization: number;
48
+ lbDiscounted: number;
49
+ };
50
+ type PesadaFooter = {
51
+ id: string;
52
+ baskets: string;
53
+ totalWeight: string;
54
+ discount: string;
55
+ netWeight: string;
56
+ weightByBasket: string;
57
+ };
58
+ export declare const useGetPesadas: (purchaseOrder: PurchaseOrderGraphQL) => [PesadaBody[], PesadaFooter, GenericDynamicTableColumn[]];
59
+ /**
60
+ * Sirve para imprimir offline
61
+ * @param formInput
62
+ * @returns
63
+ */
64
+ export declare const getPesadasByForm: (formInput: FormInput) => {
65
+ tempPesadas: PesadaBody[];
66
+ totales: {
67
+ id: string;
68
+ baskets: string;
69
+ totalWeight: string;
70
+ discount: string;
71
+ netWeight: string;
72
+ weightByBasket: string;
73
+ lbDiscounted: string;
74
+ probableUtilization: string;
75
+ };
76
+ headers: GenericDynamicTableColumn[];
77
+ };
78
+ type BasketDetailsBody = {
79
+ id: number;
80
+ total: number;
81
+ color: string;
82
+ cc: number;
83
+ };
84
+ type BasketDetailsFooter = {
85
+ id: string;
86
+ total: string;
87
+ cc: number;
88
+ };
89
+ export declare const useGetBasketDetails: (purchaseOrder: PurchaseOrderGraphQL) => [BasketDetailsBody[], BasketDetailsFooter, GenericDynamicTableColumn[]];
90
+ /**
91
+ * Para imprimir en modo offline
92
+ * @param formInput
93
+ * @returns
94
+ */
95
+ export declare const getBasketDetailsByForm: (formInput: FormInput) => {
96
+ basketDetailsArray: BasketDetailsBody[];
97
+ totales: BasketDetailsFooter;
98
+ headers: GenericDynamicTableColumn[];
99
+ };
100
+ export declare const useGetProviderNameByPurchaseOrder: (payees: PayeeGraphQL[], purchaseOrder: PurchaseOrderGraphQL) => string | null;
101
+ export declare const useGetItemNameByPurchaseOrder: (items: ItemGraphQL[], purchaseOrder: PurchaseOrderGraphQL) => string | null;
102
+ export {};
@@ -0,0 +1,333 @@
1
+ import { useFetcher } from "@remix-run/react";
2
+ import { receptionFetchStart, receptionFetchSuccess, useAppDispatch, useAppSelector, } from "@zauru-sdk/redux";
3
+ import { useEffect, useMemo, useState } from "react";
4
+ import { showAlert } from "src";
5
+ import { getBasketsSchema, reduceAdd, toFixedIfNeeded, } from "../../common/dist";
6
+ const useGetReceptionObject = (RECEPTION_NAME, { online = false, wheres = [] } = {}) => {
7
+ const fetcher = useFetcher();
8
+ const dispatch = useAppDispatch();
9
+ const objectData = useAppSelector((state) => state.receptions[RECEPTION_NAME]);
10
+ const [data, setData] = useState({
11
+ data: Array.isArray(objectData?.data)
12
+ ? objectData?.data.length
13
+ ? objectData?.data
14
+ : []
15
+ : Object.keys(objectData?.data || {}).length
16
+ ? objectData?.data
17
+ : {},
18
+ loading: objectData.loading,
19
+ });
20
+ useEffect(() => {
21
+ if (fetcher.data?.title) {
22
+ showAlert({
23
+ description: fetcher.data?.description?.toString(),
24
+ title: fetcher.data?.title?.toString(),
25
+ type: fetcher.data?.type?.toString(),
26
+ });
27
+ }
28
+ }, [fetcher.data]);
29
+ useEffect(() => {
30
+ if (fetcher.state === "idle" && fetcher.data != null) {
31
+ const receivedData = fetcher.data;
32
+ if (receivedData) {
33
+ setData({ data: receivedData[RECEPTION_NAME], loading: false });
34
+ dispatch(receptionFetchSuccess({
35
+ name: RECEPTION_NAME,
36
+ data: receivedData[RECEPTION_NAME],
37
+ }));
38
+ }
39
+ }
40
+ }, [fetcher, dispatch, RECEPTION_NAME]);
41
+ useEffect(() => {
42
+ const isEmptyData = Array.isArray(objectData?.data)
43
+ ? objectData?.data.length <= 0
44
+ : Object.keys(objectData?.data || {}).length <= 0;
45
+ if (isEmptyData || objectData.reFetch || online) {
46
+ try {
47
+ setData({ ...data, loading: true });
48
+ dispatch(receptionFetchStart(RECEPTION_NAME));
49
+ // Convierte cada elemento del array a una cadena codificada para URL
50
+ const encodedWheres = wheres.map((where) => encodeURIComponent(where));
51
+ // Une los elementos codificados con '&'
52
+ const wheresQueryParam = encodedWheres.join("&");
53
+ fetcher.load(`/api/receptions?object=${RECEPTION_NAME}&wheres=${wheresQueryParam}`);
54
+ }
55
+ catch (ex) {
56
+ showAlert({
57
+ type: "error",
58
+ title: `Ocurrió un error al cargar el object de receptions: ${RECEPTION_NAME}.`,
59
+ description: "Error: " + ex,
60
+ });
61
+ }
62
+ }
63
+ }, []);
64
+ return data;
65
+ };
66
+ export const useGetProcesses = (config) => useGetReceptionObject("queueNewReceptions", config);
67
+ export const useGetPOReceptions = (config) => useGetReceptionObject("poReceptions", config);
68
+ export const useGetBasketLots = () => useGetReceptionObject("basketLots");
69
+ export const useGetRejectionInfo = () => useGetReceptionObject("rejectionInfo");
70
+ export const useGetNewPurchaseOrderInfo = () => useGetReceptionObject("newPurchaseOrderInfo");
71
+ export const useGetPurchaseOrderGeneralInfo = () => useGetReceptionObject("purchaseOrderGeneralInfo");
72
+ export const useGetPesadas = (purchaseOrder) => {
73
+ const [pesadas, footerPesadas, headersPesadas] = useMemo(() => {
74
+ const tempPesadas = [
75
+ ...purchaseOrder.purchase_order_details?.map((x, index) => {
76
+ const parsedReference = x.reference?.split(","); //eg: "reference": "698,25,0", // peso neto, canastas, descuento
77
+ const totalWeight = parsedReference[0]
78
+ ? Number(parsedReference[0]) ?? 0
79
+ : 0;
80
+ const baskets = parsedReference[1]
81
+ ? Number(parsedReference[1]) ?? 0
82
+ : 0;
83
+ const discount = parsedReference[2]
84
+ ? Number(parsedReference[2]) ?? 0
85
+ : 0;
86
+ //TODO sacar el peso de la canasta de la API de Zauru
87
+ const basketWeight = 5;
88
+ let netWeight = totalWeight - baskets * basketWeight; //Se le resta el peso de las canastas
89
+ netWeight = netWeight * ((100 - discount) / 100); //Se le aplica el descuento
90
+ const weightByBasket = netWeight / baskets;
91
+ //Probable aprovechamiento en planta
92
+ const probableUtilization = netWeight * ((100 - purchaseOrder?.discount) / 100);
93
+ //libras o unidades descontadas
94
+ const lbDiscounted = netWeight - probableUtilization;
95
+ return {
96
+ id: index + 1,
97
+ baskets,
98
+ totalWeight,
99
+ discount,
100
+ netWeight: toFixedIfNeeded(netWeight),
101
+ weightByBasket: toFixedIfNeeded(weightByBasket),
102
+ probableUtilization,
103
+ lbDiscounted,
104
+ };
105
+ }),
106
+ ];
107
+ const totales = {
108
+ id: "",
109
+ baskets: toFixedIfNeeded(tempPesadas?.map((x) => x.baskets).reduce(reduceAdd, 0)),
110
+ totalWeight: toFixedIfNeeded(tempPesadas?.map((x) => x.totalWeight).reduce(reduceAdd, 0)),
111
+ discount: "-",
112
+ netWeight: toFixedIfNeeded(tempPesadas?.map((x) => Number(x.netWeight)).reduce(reduceAdd, 0)),
113
+ weightByBasket: "-",
114
+ lbDiscounted: toFixedIfNeeded(tempPesadas?.map((x) => Number(x.lbDiscounted)).reduce(reduceAdd, 0)),
115
+ probableUtilization: toFixedIfNeeded(tempPesadas
116
+ ?.map((x) => Number(x.probableUtilization))
117
+ .reduce(reduceAdd, 0)),
118
+ };
119
+ const headers = [
120
+ { label: "#", name: "id", type: "label", width: 5 },
121
+ { label: "Canastas", name: "baskets", type: "label" },
122
+ { label: "Peso báscula", name: "totalWeight", type: "label" },
123
+ { label: "Descuento (%)", name: "discount", type: "label" },
124
+ { label: "Peso Neto", name: "netWeight", type: "label" },
125
+ {
126
+ label: "Peso Neto - %Rechazo",
127
+ name: "probableUtilization",
128
+ type: "label",
129
+ },
130
+ {
131
+ label: "Lb o Unidades descontadas",
132
+ name: "lbDiscounted",
133
+ type: "label",
134
+ },
135
+ {
136
+ label: "Peso Neto por canasta",
137
+ name: "weightByBasket",
138
+ type: "label",
139
+ },
140
+ ];
141
+ return [tempPesadas, totales, headers];
142
+ }, [purchaseOrder]);
143
+ return [pesadas, footerPesadas, headersPesadas];
144
+ };
145
+ /**
146
+ * Sirve para imprimir offline
147
+ * @param formInput
148
+ * @returns
149
+ */
150
+ export const getPesadasByForm = (formInput) => {
151
+ // Inicializar array de pesadas
152
+ const tempPesadas = [];
153
+ // Iterar sobre los campos del formulario y extraer la información de pesadas
154
+ let index = 0;
155
+ while (formInput.hasOwnProperty(`basket${index}`)) {
156
+ const baskets = Number(formInput[`basket${index}`] || 0);
157
+ const totalWeight = Number(formInput[`weight${index}`] || 0);
158
+ const discount = Number(formInput[`discount${index}`] || 0);
159
+ // Realizar los cálculos necesarios
160
+ const basketWeight = 5;
161
+ let netWeight = totalWeight - baskets * basketWeight;
162
+ netWeight = netWeight * ((100 - discount) / 100);
163
+ const weightByBasket = netWeight / baskets;
164
+ //Probable aprovechamiento en planta
165
+ const probableUtilization = netWeight * ((100 - (Number(formInput.porcentajeRechazo) ?? 0)) / 100);
166
+ //libras o unidades descontadas
167
+ const lbDiscounted = netWeight - probableUtilization;
168
+ // Añadir al array de pesadas
169
+ tempPesadas.push({
170
+ id: index + 1,
171
+ baskets,
172
+ totalWeight,
173
+ discount,
174
+ netWeight: toFixedIfNeeded(netWeight),
175
+ weightByBasket: toFixedIfNeeded(weightByBasket),
176
+ probableUtilization,
177
+ lbDiscounted,
178
+ });
179
+ index++;
180
+ }
181
+ const totales = {
182
+ id: "",
183
+ baskets: toFixedIfNeeded(tempPesadas?.map((x) => x.baskets).reduce(reduceAdd, 0)),
184
+ totalWeight: toFixedIfNeeded(tempPesadas?.map((x) => x.totalWeight).reduce(reduceAdd, 0)),
185
+ discount: "-",
186
+ netWeight: toFixedIfNeeded(tempPesadas?.map((x) => Number(x.netWeight)).reduce(reduceAdd, 0)),
187
+ weightByBasket: "-",
188
+ lbDiscounted: toFixedIfNeeded(tempPesadas?.map((x) => Number(x.lbDiscounted)).reduce(reduceAdd, 0)),
189
+ probableUtilization: toFixedIfNeeded(tempPesadas
190
+ ?.map((x) => Number(x.probableUtilization))
191
+ .reduce(reduceAdd, 0)),
192
+ };
193
+ const headers = [
194
+ { label: "#", name: "id", type: "label", width: 5 },
195
+ { label: "Canastas", name: "baskets", type: "label" },
196
+ { label: "Peso báscula", name: "totalWeight", type: "label" },
197
+ { label: "Descuento (%)", name: "discount", type: "label" },
198
+ { label: "Peso Neto", name: "netWeight", type: "label" },
199
+ {
200
+ label: "Peso Neto - %Rechazo",
201
+ name: "probableUtilization",
202
+ type: "label",
203
+ },
204
+ {
205
+ label: "Lb o Unidades descontadas",
206
+ name: "lbDiscounted",
207
+ type: "label",
208
+ },
209
+ {
210
+ label: "Peso Neto por canasta",
211
+ name: "weightByBasket",
212
+ type: "label",
213
+ },
214
+ ];
215
+ return { tempPesadas, totales, headers };
216
+ };
217
+ export const useGetBasketDetails = (purchaseOrder) => {
218
+ const [basketsJoined, footerBasketsJoined, headersBasketsJoined] = useMemo(() => {
219
+ const bsq = purchaseOrder?.lots
220
+ ?.map((x) => {
221
+ const basket = getBasketsSchema(x.description);
222
+ return basket;
223
+ })
224
+ .flat(2) ?? [];
225
+ const bsqToCC = getBasketsSchema(purchaseOrder.memo);
226
+ const joinedBaskets = [];
227
+ for (let i = 0; i < bsq.length; i++) {
228
+ const found = joinedBaskets.find((item) => item.color === bsq[i].color);
229
+ const foundCC = bsqToCC.find((item) => item.color === bsq[i].color);
230
+ if (found) {
231
+ found.total += bsq[i].total;
232
+ }
233
+ else {
234
+ joinedBaskets.push({
235
+ id: i,
236
+ total: bsq[i].total + (foundCC ? foundCC.total : 0),
237
+ color: bsq[i].color,
238
+ cc: foundCC ? foundCC.total : 0,
239
+ });
240
+ }
241
+ }
242
+ const totales = {
243
+ id: "",
244
+ total: toFixedIfNeeded(joinedBaskets?.map((x) => x.total).reduce(reduceAdd, 0)),
245
+ cc: joinedBaskets?.map((x) => x.cc).reduce(reduceAdd, 0),
246
+ };
247
+ const headers = [
248
+ { label: "Color", name: "color", type: "label" },
249
+ { label: "Canastas recibidas", name: "total", type: "label" },
250
+ { label: "Enviadas a CC", name: "cc", type: "label" },
251
+ ];
252
+ return [joinedBaskets, totales, headers];
253
+ }, [purchaseOrder]);
254
+ return [basketsJoined, footerBasketsJoined, headersBasketsJoined];
255
+ };
256
+ /**
257
+ * Para imprimir en modo offline
258
+ * @param formInput
259
+ * @returns
260
+ */
261
+ export const getBasketDetailsByForm = (formInput) => {
262
+ const basketDetailsArray = [];
263
+ // Regex para identificar los campos relevantes
264
+ const recPattern = /^rec\d+-(.+)$/;
265
+ const qCPattern = /^qC\d+-(.+)$/;
266
+ for (const key in formInput) {
267
+ if (formInput.hasOwnProperty(key)) {
268
+ let match;
269
+ // Comprobar si la clave es un campo "rec" y extraer el color y la cantidad
270
+ if ((match = recPattern.exec(key))) {
271
+ const color = match[1];
272
+ const total = Number(formInput[key] || 0);
273
+ const existingBasket = basketDetailsArray.find((item) => item.color === color);
274
+ if (existingBasket) {
275
+ existingBasket.total += total;
276
+ }
277
+ else {
278
+ basketDetailsArray.push({
279
+ id: basketDetailsArray.length,
280
+ total,
281
+ color,
282
+ cc: 0, // Inicializar cc a 0, se actualizará más adelante si existe
283
+ });
284
+ }
285
+ }
286
+ // Comprobar si la clave es un campo "qC" y actualizar el campo cc correspondiente
287
+ if ((match = qCPattern.exec(key))) {
288
+ const color = match[1];
289
+ const cc = Number(formInput[key] || 0);
290
+ const existingBasket = basketDetailsArray.find((item) => item.color === color);
291
+ if (existingBasket) {
292
+ existingBasket.cc += cc;
293
+ }
294
+ }
295
+ }
296
+ }
297
+ // Calcular los totales para footerBasketsDetails
298
+ const totales = {
299
+ id: "",
300
+ total: basketDetailsArray
301
+ .map((x) => x.total)
302
+ .reduce((acc, val) => acc + val, 0)
303
+ .toFixed(2),
304
+ cc: basketDetailsArray.map((x) => x.cc).reduce((acc, val) => acc + val, 0),
305
+ };
306
+ // Definir los encabezados de la tabla
307
+ const headers = [
308
+ { label: "Color", name: "color", type: "label" },
309
+ { label: "Canastas recibidas", name: "total", type: "label" },
310
+ { label: "Enviadas a CC", name: "cc", type: "label" },
311
+ ];
312
+ return { basketDetailsArray, totales, headers };
313
+ };
314
+ export const useGetProviderNameByPurchaseOrder = (payees, purchaseOrder) => {
315
+ const providerName = useMemo(() => {
316
+ const provider = payees.find((x) => x.id == purchaseOrder.payee_id);
317
+ if (provider) {
318
+ return `<${provider.id_number}> ${provider.tin ? `${provider.tin} | ` : ""}${provider.name}`;
319
+ }
320
+ return null;
321
+ }, [payees, purchaseOrder]);
322
+ return providerName;
323
+ };
324
+ export const useGetItemNameByPurchaseOrder = (items, purchaseOrder) => {
325
+ const itemName = useMemo(() => {
326
+ if (purchaseOrder.purchase_order_details.length > 0 && items.length > 0) {
327
+ const item = items.find((x) => x.id == purchaseOrder.purchase_order_details[0].item_id);
328
+ return `${item?.id} - ${item?.code} - ${item?.name}`;
329
+ }
330
+ return null;
331
+ }, [items, purchaseOrder]);
332
+ return itemName;
333
+ };
@@ -0,0 +1,7 @@
1
+ export type SERVER_CONFIG_TYPES = "sessionAttribute" | "environment" | "sessionVariable";
2
+ /**
3
+ *
4
+ * @param attribute
5
+ * @returns
6
+ */
7
+ export declare const useGetSessionAttribute: (name: string, type: SERVER_CONFIG_TYPES) => string;