npm-pkg-hook 1.10.4 → 1.10.7
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.
- package/package.json +1 -1
- package/src/hooks/index.js +7 -0
- package/src/hooks/useImagesStore/queries.js +1 -67
- package/src/hooks/usePWAInstall/index.js +20 -20
- package/src/hooks/useProductsFood/index.js +44 -27
- package/src/hooks/useProductsFood/queriesStore.js +13 -1
- package/src/hooks/useReport/index.js +1 -1
- package/src/hooks/useSales/index.js +43 -16
- package/src/hooks/useSales/useTotalSales.js +11 -12
- package/src/hooks/useStockMovements/helpers/index.js +16 -0
- package/src/hooks/useStockMovements/index.js +38 -0
- package/src/hooks/useTopProductsMovements/index.js +27 -0
- package/src/hooks/useTotalAllSales/index.js +25 -0
- package/src/hooks/useTotalProductsInStock/index.js +23 -0
- package/src/hooks/useTotalProductsSold/index.js +23 -0
- package/src/hooks/useTotalProductsSolded/index.js +20 -0
- package/src/hooks/useUpdateMultipleProducts/index.js +1 -1
- package/src/hooks/useUploadProducts/index.js +2 -0
- package/src/hooks/useWeeklyStockMovement/helpers/index.js +32 -0
- package/src/hooks/useWeeklyStockMovement/index.js +51 -0
- package/src/utils/UtilDateRange.js +31 -0
- package/src/utils/index.js +2 -0
package/package.json
CHANGED
package/src/hooks/index.js
CHANGED
|
@@ -123,3 +123,10 @@ export * from './useGetStoreCookie'
|
|
|
123
123
|
export * from './getGlobalSession'
|
|
124
124
|
export * from './handleLogin'
|
|
125
125
|
export * from './useInventory'
|
|
126
|
+
export * from './useStockMovements'
|
|
127
|
+
export * from './useTopProductsMovements'
|
|
128
|
+
export * from './useTotalProductsSold'
|
|
129
|
+
export * from './useTotalProductsInStock/index'
|
|
130
|
+
export * from './useTotalAllSales/index'
|
|
131
|
+
export * from './useTotalProductsSolded'
|
|
132
|
+
export * from './useWeeklyStockMovement'
|
|
@@ -74,73 +74,7 @@ export const GET_ALL_EMPLOYEE_STORE = gql`
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
`
|
|
77
|
-
|
|
78
|
-
query productFoodsAll(
|
|
79
|
-
$search: String
|
|
80
|
-
$min: Int
|
|
81
|
-
$max: Int
|
|
82
|
-
$gender: [String]
|
|
83
|
-
$pState: Int
|
|
84
|
-
$desc: [String]
|
|
85
|
-
$categories: [ID]
|
|
86
|
-
$fromDate: DateTime
|
|
87
|
-
$toDate: DateTime
|
|
88
|
-
) {
|
|
89
|
-
productFoodsAll(
|
|
90
|
-
search: $search
|
|
91
|
-
min: $min
|
|
92
|
-
max: $max
|
|
93
|
-
gender: $gender
|
|
94
|
-
desc: $desc
|
|
95
|
-
pState: $pState
|
|
96
|
-
categories: $categories
|
|
97
|
-
toDate: $toDate
|
|
98
|
-
fromDate: $fromDate
|
|
99
|
-
) {
|
|
100
|
-
pId
|
|
101
|
-
sizeId #Talla
|
|
102
|
-
colorId #Color
|
|
103
|
-
cId #Country
|
|
104
|
-
dId #Department
|
|
105
|
-
ctId #Cuidad
|
|
106
|
-
fId #Características
|
|
107
|
-
pName
|
|
108
|
-
ProPrice
|
|
109
|
-
ProDescuento
|
|
110
|
-
free
|
|
111
|
-
manageStock
|
|
112
|
-
ProUniDisponibles
|
|
113
|
-
ProDescription
|
|
114
|
-
ProProtegido
|
|
115
|
-
ProAssurance
|
|
116
|
-
ValueDelivery
|
|
117
|
-
ProStar
|
|
118
|
-
sTateLogistic
|
|
119
|
-
ProImage
|
|
120
|
-
ProWidth
|
|
121
|
-
ProHeight
|
|
122
|
-
ProLength
|
|
123
|
-
ProWeight
|
|
124
|
-
ProQuantity
|
|
125
|
-
ProOutstanding
|
|
126
|
-
pDatCre
|
|
127
|
-
pDatMod
|
|
128
|
-
ProDelivery
|
|
129
|
-
ProVoltaje
|
|
130
|
-
stock
|
|
131
|
-
pState
|
|
132
|
-
feat {
|
|
133
|
-
fId
|
|
134
|
-
thpId
|
|
135
|
-
hpqrQuestion
|
|
136
|
-
}
|
|
137
|
-
area {
|
|
138
|
-
aId
|
|
139
|
-
aName
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
`
|
|
77
|
+
|
|
144
78
|
export const GET_ALL_RATING_START_STORE = gql`
|
|
145
79
|
query getAllRatingStar($idStore: ID) {
|
|
146
80
|
getAllRatingStar(idStore: $idStore) {
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react'
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
2
|
|
|
3
3
|
export const usePWAInstall = () => {
|
|
4
|
-
const [deferredPrompt, setDeferredPrompt] = useState(null)
|
|
5
|
-
const [isInstallable, setIsInstallable] = useState(false)
|
|
4
|
+
const [deferredPrompt, setDeferredPrompt] = useState(null)
|
|
5
|
+
const [isInstallable, setIsInstallable] = useState(false)
|
|
6
6
|
|
|
7
7
|
useEffect(() => {
|
|
8
8
|
const handleBeforeInstallPrompt = (e) => {
|
|
9
|
-
e.preventDefault()
|
|
10
|
-
setDeferredPrompt(e)
|
|
11
|
-
setIsInstallable(true)
|
|
12
|
-
}
|
|
9
|
+
e.preventDefault() // Evita que el navegador muestre el diálogo automáticamente
|
|
10
|
+
setDeferredPrompt(e) // Almacena el evento para que puedas llamarlo más tarde
|
|
11
|
+
setIsInstallable(true) // Marca que la PWA es instalable
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
|
|
14
|
+
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
|
|
15
15
|
|
|
16
16
|
return () => {
|
|
17
|
-
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
|
|
18
|
-
}
|
|
19
|
-
}, [])
|
|
17
|
+
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
|
|
18
|
+
}
|
|
19
|
+
}, [])
|
|
20
20
|
|
|
21
21
|
const installPWA = () => {
|
|
22
22
|
if (deferredPrompt) {
|
|
23
|
-
deferredPrompt.prompt()
|
|
23
|
+
deferredPrompt.prompt()
|
|
24
24
|
|
|
25
25
|
deferredPrompt.userChoice.then((choiceResult) => {
|
|
26
26
|
if (choiceResult.outcome === 'accepted') {
|
|
27
|
-
console.log('User accepted the install prompt')
|
|
27
|
+
console.log('User accepted the install prompt')
|
|
28
28
|
} else {
|
|
29
|
-
console.log('User dismissed the install prompt')
|
|
29
|
+
console.log('User dismissed the install prompt')
|
|
30
30
|
}
|
|
31
|
-
setDeferredPrompt(null)
|
|
32
|
-
setIsInstallable(false)
|
|
33
|
-
})
|
|
31
|
+
setDeferredPrompt(null) // Limpia el evento después de usarlo
|
|
32
|
+
setIsInstallable(false) // Oculta el botón de instalación
|
|
33
|
+
})
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|
|
36
36
|
|
|
37
|
-
return { isInstallable, installPWA }
|
|
38
|
-
}
|
|
37
|
+
return { isInstallable, installPWA }
|
|
38
|
+
}
|
|
@@ -14,51 +14,68 @@ import {
|
|
|
14
14
|
export * from './useEditProduct'
|
|
15
15
|
|
|
16
16
|
export const useProductsFood = ({
|
|
17
|
-
categories,
|
|
18
|
-
desc,
|
|
17
|
+
categories = [],
|
|
18
|
+
desc = [],
|
|
19
19
|
fetchPolicy = 'cache-and-network',
|
|
20
|
-
fromDate,
|
|
21
|
-
gender,
|
|
20
|
+
fromDate = null,
|
|
21
|
+
gender = [],
|
|
22
22
|
max = 100,
|
|
23
|
-
min,
|
|
23
|
+
min = null,
|
|
24
24
|
pState,
|
|
25
25
|
search = null,
|
|
26
|
-
toDate
|
|
26
|
+
toDate = null,
|
|
27
|
+
dataSale = [],
|
|
28
|
+
isShopppingCard = false
|
|
27
29
|
}) => {
|
|
28
|
-
// const [productsFood, setProductsFood] = useState([])
|
|
29
30
|
const [showMore, setShowMore] = useState(500)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
loading,
|
|
33
|
-
fetchMore,
|
|
34
|
-
error,
|
|
35
|
-
called
|
|
36
|
-
} = useQuery(GET_ALL_PRODUCT_STORE, {
|
|
31
|
+
|
|
32
|
+
const { data, loading, fetchMore, refetch, error, called } = useQuery(GET_ALL_PRODUCT_STORE, {
|
|
37
33
|
fetchPolicy,
|
|
38
34
|
notifyOnNetworkStatusChange: true,
|
|
39
35
|
nextFetchPolicy: 'cache-first',
|
|
40
36
|
refetchWritePolicy: 'merge',
|
|
41
|
-
variables:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
min: min || null,
|
|
37
|
+
variables: {
|
|
38
|
+
categories,
|
|
39
|
+
desc,
|
|
40
|
+
fromDate,
|
|
41
|
+
gender,
|
|
42
|
+
max,
|
|
43
|
+
min,
|
|
49
44
|
pState,
|
|
50
|
-
search
|
|
51
|
-
toDate
|
|
45
|
+
search,
|
|
46
|
+
toDate
|
|
52
47
|
}
|
|
53
48
|
})
|
|
54
49
|
|
|
55
|
-
const productsFood = data?.productFoodsAll
|
|
50
|
+
const productsFood = data?.productFoodsAll?.data ?? []
|
|
51
|
+
|
|
52
|
+
if (!isShopppingCard) {
|
|
53
|
+
return [
|
|
54
|
+
productsFood, {
|
|
55
|
+
pagination: data?.productFoodsAll?.pagination || {},
|
|
56
|
+
loading: called ? false : loading,
|
|
57
|
+
error,
|
|
58
|
+
showMore,
|
|
59
|
+
fetchMore,
|
|
60
|
+
refetch,
|
|
61
|
+
setShowMore
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const updatedProductsFood = productsFood.map(product => ({
|
|
67
|
+
...product,
|
|
68
|
+
existsInSale: dataSale.some(item => item.pId === product.pId)
|
|
69
|
+
}));
|
|
70
|
+
|
|
56
71
|
return [
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
updatedProductsFood, {
|
|
73
|
+
pagination: data?.productFoodsAll?.pagination || {},
|
|
59
74
|
loading: called ? false : loading,
|
|
75
|
+
error,
|
|
60
76
|
showMore,
|
|
61
77
|
fetchMore,
|
|
78
|
+
refetch,
|
|
62
79
|
setShowMore
|
|
63
80
|
}
|
|
64
81
|
]
|
|
@@ -76,7 +76,7 @@ export const GET_ALL_EMPLOYEE_STORE = gql`
|
|
|
76
76
|
`
|
|
77
77
|
|
|
78
78
|
export const GET_ALL_PRODUCT_STORE = gql`
|
|
79
|
-
|
|
79
|
+
query productFoodsAll(
|
|
80
80
|
$search: String
|
|
81
81
|
$min: Int
|
|
82
82
|
$max: Int
|
|
@@ -86,6 +86,7 @@ export const GET_ALL_PRODUCT_STORE = gql`
|
|
|
86
86
|
$categories: [ID]
|
|
87
87
|
$fromDate: DateTime
|
|
88
88
|
$toDate: DateTime
|
|
89
|
+
$page: Int
|
|
89
90
|
) {
|
|
90
91
|
productFoodsAll(
|
|
91
92
|
search: $search
|
|
@@ -97,7 +98,17 @@ export const GET_ALL_PRODUCT_STORE = gql`
|
|
|
97
98
|
categories: $categories
|
|
98
99
|
toDate: $toDate
|
|
99
100
|
fromDate: $fromDate
|
|
101
|
+
page: $page
|
|
100
102
|
) {
|
|
103
|
+
success
|
|
104
|
+
message
|
|
105
|
+
pagination {
|
|
106
|
+
totalRecords
|
|
107
|
+
totalPages
|
|
108
|
+
currentPage
|
|
109
|
+
__typename
|
|
110
|
+
}
|
|
111
|
+
data {
|
|
101
112
|
pId
|
|
102
113
|
sizeId #Talla
|
|
103
114
|
colorId #Color
|
|
@@ -149,6 +160,7 @@ export const GET_ALL_PRODUCT_STORE = gql`
|
|
|
149
160
|
aName
|
|
150
161
|
}
|
|
151
162
|
}
|
|
163
|
+
}
|
|
152
164
|
}
|
|
153
165
|
`
|
|
154
166
|
export const GET_ALL_RATING_START_STORE = gql`
|
|
@@ -34,7 +34,7 @@ export const useReport = ({
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
const totalSales = totalSalesData?.getAllSalesStoreTotal ?? {}
|
|
37
|
-
|
|
37
|
+
console.log(totalSales)
|
|
38
38
|
return {
|
|
39
39
|
getAllSalesStore: lazyQuery ? getAllSalesStore : () => { }, // Return function only if in lazy mode
|
|
40
40
|
data: lazyQuery ? lazyDataSales : data, // Use data from lazy query if available
|
|
@@ -75,6 +75,7 @@ export const useSales = ({
|
|
|
75
75
|
const [search, setSearch] = useState('')
|
|
76
76
|
const [datCat] = useCatWithProduct({})
|
|
77
77
|
const [categories, setCategories] = useState([])
|
|
78
|
+
const [currentPage, setCurrentPage] = useState(1)
|
|
78
79
|
useEffect(() => {
|
|
79
80
|
setCategories(datCat)
|
|
80
81
|
}, [datCat])
|
|
@@ -102,6 +103,9 @@ export const useSales = ({
|
|
|
102
103
|
const [valuesDates, setValuesDates] = useState(() => {
|
|
103
104
|
return { fromDate: yearMonthDay, toDate: '' }
|
|
104
105
|
})
|
|
106
|
+
const [product, setProduct] = useState({
|
|
107
|
+
PRODUCT: {}
|
|
108
|
+
})
|
|
105
109
|
const [loadingExtraProduct, setLoadingExtraProduct] = useState(false)
|
|
106
110
|
const [dataOptional, setDataOptional] = useState([])
|
|
107
111
|
const [dataExtra, setDataExtra] = useState([])
|
|
@@ -134,12 +138,9 @@ export const useSales = ({
|
|
|
134
138
|
}
|
|
135
139
|
}
|
|
136
140
|
)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const [productFoodsOne, { data: dataProduct }] = useLazyQuery(
|
|
141
|
-
GET_ONE_PRODUCTS_FOOD
|
|
142
|
-
)
|
|
141
|
+
|
|
142
|
+
const [productFoodsOne, { data: dataProduct }] = useLazyQuery(GET_ONE_PRODUCTS_FOOD)
|
|
143
|
+
|
|
143
144
|
const [ExtProductFoodsSubOptionalAll, { loading: loadingExtProductFoodsSubOptionalAll }] = useLazyQuery(
|
|
144
145
|
GET_EXTRAS_PRODUCT_FOOD_OPTIONAL,
|
|
145
146
|
{
|
|
@@ -153,7 +154,13 @@ export const useSales = ({
|
|
|
153
154
|
setDataExtra([])
|
|
154
155
|
}
|
|
155
156
|
})
|
|
156
|
-
|
|
157
|
+
|
|
158
|
+
const [productsFood, {
|
|
159
|
+
loading,
|
|
160
|
+
fetchMore,
|
|
161
|
+
pagination,
|
|
162
|
+
refetch
|
|
163
|
+
}] = useProductsFood({
|
|
157
164
|
// @ts-ignore
|
|
158
165
|
search: search?.length >= 4 ? search : '',
|
|
159
166
|
gender: [],
|
|
@@ -162,8 +169,17 @@ export const useSales = ({
|
|
|
162
169
|
toDate: valuesDates?.toDate,
|
|
163
170
|
fromDate: valuesDates?.fromDate,
|
|
164
171
|
max: showMore,
|
|
165
|
-
min: 0
|
|
172
|
+
min: 0,
|
|
173
|
+
isShopppingCard: true,
|
|
174
|
+
dataSale: (Array.isArray(saveDataState?.PRODUCT) && saveDataState?.PRODUCT) ?? [],
|
|
175
|
+
callback: () => { return null }
|
|
166
176
|
})
|
|
177
|
+
|
|
178
|
+
const handlePageChange = (pageNumber) => {
|
|
179
|
+
setCurrentPage(pageNumber)
|
|
180
|
+
refetch({ page: pageNumber })
|
|
181
|
+
}
|
|
182
|
+
|
|
167
183
|
const handleChangeCheck = (caId) => {
|
|
168
184
|
// @ts-ignore
|
|
169
185
|
setCategories((prev) => {
|
|
@@ -176,7 +192,6 @@ export const useSales = ({
|
|
|
176
192
|
})
|
|
177
193
|
})
|
|
178
194
|
}
|
|
179
|
-
|
|
180
195
|
const max = productsFood?.reduce(function (a, b) {
|
|
181
196
|
return Math.max(a, b?.ProPrice || 0)
|
|
182
197
|
}, 0)
|
|
@@ -367,7 +382,7 @@ export const useSales = ({
|
|
|
367
382
|
|
|
368
383
|
// Validar si se intenta superar el stock disponible
|
|
369
384
|
const finalQuantity = Math.min(value, productExist.stock)
|
|
370
|
-
if (value > productExist.stock) {
|
|
385
|
+
if ((value > productExist.stock) && productExist.manageStock) {
|
|
371
386
|
sendNotification({
|
|
372
387
|
title: 'Stock insuficiente',
|
|
373
388
|
backgroundColor: 'warning',
|
|
@@ -469,7 +484,8 @@ export const useSales = ({
|
|
|
469
484
|
}
|
|
470
485
|
|
|
471
486
|
// Validar si se supera el stock
|
|
472
|
-
|
|
487
|
+
console.log(OurProduct)
|
|
488
|
+
if (newQuantity >= OurProduct?.stock && OurProduct?.manageStock) {
|
|
473
489
|
sendNotification({
|
|
474
490
|
title: 'Stock insuficiente',
|
|
475
491
|
backgroundColor: 'warning',
|
|
@@ -477,7 +493,6 @@ export const useSales = ({
|
|
|
477
493
|
})
|
|
478
494
|
return items // Retornar el producto sin modificar
|
|
479
495
|
}
|
|
480
|
-
|
|
481
496
|
return {
|
|
482
497
|
...items,
|
|
483
498
|
ProQuantity: newQuantity,
|
|
@@ -776,8 +791,8 @@ export const useSales = ({
|
|
|
776
791
|
const OurProduct = productsFood?.find((item) => item.pId === pId)
|
|
777
792
|
const isFree = productExist?.free
|
|
778
793
|
const currentQuantity = productExist?.ProQuantity || 0
|
|
779
|
-
|
|
780
|
-
if (
|
|
794
|
+
|
|
795
|
+
if (OurProduct?.manageStock && isStockInsufficient(currentQuantity, OurProduct?.stock)) {
|
|
781
796
|
sendAlertStock(stock)
|
|
782
797
|
return state
|
|
783
798
|
}
|
|
@@ -1062,7 +1077,6 @@ export const useSales = ({
|
|
|
1062
1077
|
cache.modify({
|
|
1063
1078
|
fields: {
|
|
1064
1079
|
productFoodsAll (existingProductFoodsAll = []) {
|
|
1065
|
-
console.log('existingProductFoodsAll', existingProductFoodsAll)
|
|
1066
1080
|
return existingProductFoodsAll
|
|
1067
1081
|
}
|
|
1068
1082
|
}
|
|
@@ -1276,6 +1290,16 @@ export const useSales = ({
|
|
|
1276
1290
|
// Filtrar los productos de productsFood por los carProIds obtenidos
|
|
1277
1291
|
const filteredProducts = filterProductsByCarProId(productsFood, carProIds)
|
|
1278
1292
|
|
|
1293
|
+
const allProducts = useMemo(() => {
|
|
1294
|
+
const productMap = new Map(data.PRODUCT.map(item => [String(item.pId), item.ProQuantity || 0]))
|
|
1295
|
+
|
|
1296
|
+
return filteredProducts.map(product => ({
|
|
1297
|
+
...product,
|
|
1298
|
+
existsInSale: productMap.has(String(product.pId)),
|
|
1299
|
+
ProQuantity: productMap.get(String(product.pId)) || 0
|
|
1300
|
+
}))
|
|
1301
|
+
}, [data.PRODUCT, filteredProducts])
|
|
1302
|
+
|
|
1279
1303
|
return {
|
|
1280
1304
|
loading: loading || loadingSale,
|
|
1281
1305
|
loadingExtraProduct,
|
|
@@ -1300,7 +1324,7 @@ export const useSales = ({
|
|
|
1300
1324
|
search,
|
|
1301
1325
|
values,
|
|
1302
1326
|
initialStateSales,
|
|
1303
|
-
productsFood:
|
|
1327
|
+
productsFood: allProducts,
|
|
1304
1328
|
modalItem,
|
|
1305
1329
|
sumExtraProducts,
|
|
1306
1330
|
oneProductToComment: oneProductToComment ?? null,
|
|
@@ -1308,13 +1332,16 @@ export const useSales = ({
|
|
|
1308
1332
|
dataOptional: dataOptional || [],
|
|
1309
1333
|
dataExtra: dataExtra || [],
|
|
1310
1334
|
fetchMore,
|
|
1335
|
+
pagination,
|
|
1311
1336
|
discount,
|
|
1312
1337
|
datCat: categories,
|
|
1338
|
+
currentPage,
|
|
1313
1339
|
loadingProduct: loading,
|
|
1314
1340
|
handleChangeCheck,
|
|
1315
1341
|
errors,
|
|
1316
1342
|
handleUpdateAllExtra,
|
|
1317
1343
|
dispatch,
|
|
1344
|
+
handlePageChange,
|
|
1318
1345
|
handleComment,
|
|
1319
1346
|
setModalItem,
|
|
1320
1347
|
handleChangeFilter,
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import { useApolloClient, useQuery } from '@apollo/client'
|
|
2
|
-
import { useState } from 'react'
|
|
3
2
|
import { GET_ALL_COUNT_SALES } from './queries'
|
|
4
3
|
|
|
5
4
|
export const useTotalSales = () => {
|
|
6
|
-
const [count, setCount] = useState(0)
|
|
7
5
|
const client = useApolloClient()
|
|
8
6
|
|
|
9
|
-
const { loading, error } = useQuery(GET_ALL_COUNT_SALES, {
|
|
10
|
-
onCompleted: (data) => {
|
|
11
|
-
if (data) {
|
|
12
|
-
client.writeQuery({ query: GET_ALL_COUNT_SALES, data }) // Almacena la respuesta en la cache
|
|
13
|
-
}
|
|
14
|
-
if (data?.getTodaySales) {
|
|
15
|
-
setCount(data?.getTodaySales || 0)
|
|
16
|
-
}
|
|
17
|
-
},
|
|
7
|
+
const { data, loading, error } = useQuery(GET_ALL_COUNT_SALES, {
|
|
18
8
|
fetchPolicy: 'cache-and-network',
|
|
19
9
|
notifyOnNetworkStatusChange: true,
|
|
20
10
|
nextFetchPolicy: 'cache-first',
|
|
21
11
|
refetchWritePolicy: 'merge'
|
|
22
12
|
})
|
|
23
|
-
|
|
13
|
+
|
|
14
|
+
// Guarda la respuesta en la caché manualmente (opcional)
|
|
15
|
+
if (data) {
|
|
16
|
+
client.writeQuery({ query: GET_ALL_COUNT_SALES, data })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return [data?.getTodaySales || 0, {
|
|
20
|
+
loading,
|
|
21
|
+
error
|
|
22
|
+
}]
|
|
24
23
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const fillMissingDates = (data, days = 7) => {
|
|
2
|
+
const today = new Date()
|
|
3
|
+
const filledData = []
|
|
4
|
+
|
|
5
|
+
for (let i = days - 1; i >= 0; i--) {
|
|
6
|
+
const date = new Date()
|
|
7
|
+
date.setDate(today.getDate() - i)
|
|
8
|
+
|
|
9
|
+
const formattedDate = date.toISOString().split('T')[0] // "YYYY-MM-DD"
|
|
10
|
+
const existingData = data.find(item => item.date === formattedDate)
|
|
11
|
+
|
|
12
|
+
filledData.push(existingData || { date: formattedDate, TotalIn: 0, TotalOut: 0, TotalAdjustment: 0 })
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return filledData
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
import { useQuery, gql } from '@apollo/client'
|
|
3
|
+
import { fillMissingDates } from './helpers'
|
|
4
|
+
|
|
5
|
+
const GET_STOCK_MOVEMENTS = gql`
|
|
6
|
+
query {
|
|
7
|
+
getStockMovementsByDay {
|
|
8
|
+
date
|
|
9
|
+
total_in,
|
|
10
|
+
total_adjustment
|
|
11
|
+
total_out
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Custom hook to fetch stock movements data for visualization.
|
|
18
|
+
* @returns {Object} { data, loading, error }
|
|
19
|
+
*/
|
|
20
|
+
export const useStockMovements = () => {
|
|
21
|
+
const { data, loading, error } = useQuery(GET_STOCK_MOVEMENTS)
|
|
22
|
+
const [chartData, setChartData] = useState([])
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (data && data.getStockMovementsByDay) {
|
|
26
|
+
// Transform data to be compatible with Recharts
|
|
27
|
+
const formattedData = data.getStockMovementsByDay.map(entry => ({
|
|
28
|
+
date: entry.date,
|
|
29
|
+
TotalIn: entry.total_in ?? 0,
|
|
30
|
+
TotalOut: entry.total_out ?? 0,
|
|
31
|
+
TotalAdjustment: entry.total_adjustment ?? 0
|
|
32
|
+
}))
|
|
33
|
+
setChartData(formattedData)
|
|
34
|
+
}
|
|
35
|
+
}, [data])
|
|
36
|
+
|
|
37
|
+
return [fillMissingDates(chartData), { loading, error }]
|
|
38
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GraphQL query to fetch top-selling products movements
|
|
5
|
+
*/
|
|
6
|
+
const GET_TOP_PRODUCTS_MOVEMENTS = gql`
|
|
7
|
+
query {
|
|
8
|
+
getTopProductsMovements {
|
|
9
|
+
productName
|
|
10
|
+
idProduct
|
|
11
|
+
totalMovements
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Custom hook to fetch and return the top-selling products movements
|
|
18
|
+
* @returns {Object} - { data, loading, error }
|
|
19
|
+
*/
|
|
20
|
+
export const useTopProductsMovements = () => {
|
|
21
|
+
const { data, loading, error } = useQuery(GET_TOP_PRODUCTS_MOVEMENTS)
|
|
22
|
+
|
|
23
|
+
return [data?.getTopProductsMovements, {
|
|
24
|
+
loading,
|
|
25
|
+
error
|
|
26
|
+
}]
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client'
|
|
2
|
+
|
|
3
|
+
const GET_TOTAL_SALES = gql`
|
|
4
|
+
query totalSales {
|
|
5
|
+
totalSales {
|
|
6
|
+
success
|
|
7
|
+
message
|
|
8
|
+
totalSales
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Custom hook to fetch total sales from GraphQL API.
|
|
15
|
+
* @returns {Object} An object containing total sales, loading state, error, and refetch function.
|
|
16
|
+
*/
|
|
17
|
+
export const useTotalAllSales = () => {
|
|
18
|
+
const { data, loading, error, refetch } = useQuery(GET_TOTAL_SALES)
|
|
19
|
+
|
|
20
|
+
return [data?.totalSales?.totalSales, {
|
|
21
|
+
loading,
|
|
22
|
+
error,
|
|
23
|
+
refetch
|
|
24
|
+
}]
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GraphQL query to fetch total products in stock.
|
|
5
|
+
*/
|
|
6
|
+
const GET_TOTAL_PRODUCTS_IN_STOCK = gql`
|
|
7
|
+
query getTotalProductsInStock {
|
|
8
|
+
getTotalProductsInStock
|
|
9
|
+
}
|
|
10
|
+
`
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Custom hook to fetch total products in stock.
|
|
14
|
+
* @returns {Object} - { totalProductsInStock, loading, error }
|
|
15
|
+
*/
|
|
16
|
+
export const useTotalProductsInStock = () => {
|
|
17
|
+
const { data, loading, error } = useQuery(GET_TOTAL_PRODUCTS_IN_STOCK)
|
|
18
|
+
|
|
19
|
+
return [data?.getTotalProductsInStock ?? 0, {
|
|
20
|
+
loading,
|
|
21
|
+
error
|
|
22
|
+
}]
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GraphQL query to fetch total products sold.
|
|
5
|
+
*/
|
|
6
|
+
const GET_TOTAL_PRODUCTS_SOLD = gql`
|
|
7
|
+
query getTotalSalesSold {
|
|
8
|
+
getTotalSalesSold
|
|
9
|
+
}
|
|
10
|
+
`
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Custom hook to fetch total products sold.
|
|
14
|
+
* @returns {Object} - { totalProductsSold, loading, error }
|
|
15
|
+
*/
|
|
16
|
+
export const useTotalProductsSold = () => {
|
|
17
|
+
const { data, loading, error } = useQuery(GET_TOTAL_PRODUCTS_SOLD)
|
|
18
|
+
|
|
19
|
+
return [data?.getTotalSalesSold || 0, {
|
|
20
|
+
loading,
|
|
21
|
+
error
|
|
22
|
+
}]
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client'
|
|
2
|
+
|
|
3
|
+
const GET_TOTAL_PRODUCTS_SOLD = gql`
|
|
4
|
+
query {
|
|
5
|
+
getTotalProductsSold
|
|
6
|
+
}
|
|
7
|
+
`
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Custom hook to fetch the total number of products sold.
|
|
11
|
+
* @returns {{ totalSold: number, loading: boolean, error: any }}
|
|
12
|
+
*/
|
|
13
|
+
export const useTotalProductsSolded = () => {
|
|
14
|
+
const { data, loading, error } = useQuery(GET_TOTAL_PRODUCTS_SOLD)
|
|
15
|
+
|
|
16
|
+
return [data?.getTotalProductsSold, {
|
|
17
|
+
loading,
|
|
18
|
+
error
|
|
19
|
+
}]
|
|
20
|
+
}
|
|
@@ -59,7 +59,9 @@ export const useUploadProducts = ({
|
|
|
59
59
|
pCode: code,
|
|
60
60
|
editing: false,
|
|
61
61
|
PRECIO_AL_PUBLICO,
|
|
62
|
+
ProImage: '/images/placeholder-image.webp',
|
|
62
63
|
VALOR_DE_COMPRA,
|
|
64
|
+
manageStock: true,
|
|
63
65
|
errors: validationErrors.length > 0 ? validationErrors : null
|
|
64
66
|
}
|
|
65
67
|
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fills missing weeks for the last 7 weeks, ensuring continuous data.
|
|
3
|
+
* If a week is missing, it fills it with totalOut: 0 and percentageChange: "N/A".
|
|
4
|
+
*
|
|
5
|
+
* @param {Array} data - Array of weekly stock movement objects.
|
|
6
|
+
* @returns {Array} - Filled data ensuring the last 7 weeks are covered.
|
|
7
|
+
*/
|
|
8
|
+
export const fillLast7Weeks = (data) => {
|
|
9
|
+
const today = new Date()
|
|
10
|
+
const last7Weeks = []
|
|
11
|
+
|
|
12
|
+
// Generar las últimas 7 semanas (cada lunes)
|
|
13
|
+
for (let i = 6; i >= 0; i--) {
|
|
14
|
+
const weekDate = new Date(today)
|
|
15
|
+
weekDate.setDate(today.getDate() - today.getDay() - (i * 7) + 1) // Ajustar para que sea lunes
|
|
16
|
+
const weekStart = weekDate.toISOString().split('T')[0] // Formato YYYY-MM-DD
|
|
17
|
+
last7Weeks.push(weekStart)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Mapear los datos existentes para acceso rápido
|
|
21
|
+
const dataMap = new Map(data.map(item => [item.weekStart, item]))
|
|
22
|
+
|
|
23
|
+
// Construir la nueva lista asegurando que todas las semanas estén presentes
|
|
24
|
+
return last7Weeks.map(weekStart => (
|
|
25
|
+
dataMap.get(weekStart) || {
|
|
26
|
+
weekStart,
|
|
27
|
+
totalOut: 0,
|
|
28
|
+
prevTotalOut: null,
|
|
29
|
+
percentageChange: 'N/A'
|
|
30
|
+
}
|
|
31
|
+
))
|
|
32
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { gql, useQuery } from '@apollo/client'
|
|
2
|
+
import { fillLast7Weeks } from './helpers' // Asegúrate de importar el helper
|
|
3
|
+
|
|
4
|
+
const GET_WEEKLY_STOCK_MOVEMENT = gql`
|
|
5
|
+
query GetStockMovementPercentageChange {
|
|
6
|
+
getStockMovementWeeklyComparison {
|
|
7
|
+
weekStart
|
|
8
|
+
totalOut
|
|
9
|
+
prevTotalOut
|
|
10
|
+
percentageChange
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
`
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Custom hook to fetch and format weekly stock movement data.
|
|
17
|
+
* @returns {Object} - { data, loading, error, formattedData }
|
|
18
|
+
*/
|
|
19
|
+
export const useWeeklyStockMovement = () => {
|
|
20
|
+
const { data, loading, error } = useQuery(GET_WEEKLY_STOCK_MOVEMENT)
|
|
21
|
+
|
|
22
|
+
// Transform data and fill missing weeks
|
|
23
|
+
const rawData = data?.getStockMovementWeeklyComparison || []
|
|
24
|
+
const formattedData = fillLast7Weeks(
|
|
25
|
+
rawData.map(item => ({
|
|
26
|
+
...item,
|
|
27
|
+
percentageChange: formatPercentageChange(item.percentageChange)
|
|
28
|
+
}))
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return [formattedData, { loading, error }]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Ensures percentageChange is a valid string percentage, clamping between -100% and 100%.
|
|
36
|
+
*
|
|
37
|
+
* @param {string | null} percentageChange - Raw percentage change value.
|
|
38
|
+
* @returns {string} - Formatted and clamped percentage change.
|
|
39
|
+
*/
|
|
40
|
+
const formatPercentageChange = (percentageChange) => {
|
|
41
|
+
if (percentageChange === null) return 'N/A'
|
|
42
|
+
|
|
43
|
+
// Convertir a número
|
|
44
|
+
let parsedValue = parseFloat(percentageChange)
|
|
45
|
+
|
|
46
|
+
// Clampear entre -100% y 100%
|
|
47
|
+
if (isNaN(parsedValue)) return 'N/A'
|
|
48
|
+
parsedValue = Math.max(-100, Math.min(100, parsedValue))
|
|
49
|
+
|
|
50
|
+
return `${parsedValue.toFixed(1)}`
|
|
51
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class UtilDateRange {
|
|
2
|
+
constructor (date = new Date()) {
|
|
3
|
+
this.date = new Date(date) // Asegura que sea un objeto Date
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
toLocalTime (date) {
|
|
7
|
+
const offset = -5 // UTC-5 (ajustar si es necesario)
|
|
8
|
+
const localDate = new Date(date)
|
|
9
|
+
localDate.setHours(localDate.getHours() + offset)
|
|
10
|
+
return localDate
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getStartOfDay () {
|
|
14
|
+
const localDate = this.toLocalTime(this.date)
|
|
15
|
+
localDate.setHours(0, 0, 0, 0)
|
|
16
|
+
return localDate
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getEndOfDay () {
|
|
20
|
+
const localDate = this.toLocalTime(this.date)
|
|
21
|
+
localDate.setHours(23, 59, 59, 999)
|
|
22
|
+
return localDate
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getRange () {
|
|
26
|
+
return {
|
|
27
|
+
start: this.getStartOfDay(),
|
|
28
|
+
end: this.getEndOfDay()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|