92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
|
|
import {Dispatch, SetStateAction, useEffect, useRef} from 'react';
|
||
|
|
import { getCartUpdates } from '../api/promoApi';
|
||
|
|
import { normalizeProductImage } from '../utils/product';
|
||
|
|
import type { Product } from '../types/cart';
|
||
|
|
|
||
|
|
interface UseCartPollingParams {
|
||
|
|
enabled: boolean;
|
||
|
|
onProductsChange: Dispatch<SetStateAction<Product[]>>;
|
||
|
|
onComplete: () => void;
|
||
|
|
onLoadingChange: (isLoading: boolean) => void;
|
||
|
|
setDisplayText: Dispatch<SetStateAction<string>>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function useCartPolling({
|
||
|
|
enabled,
|
||
|
|
onProductsChange,
|
||
|
|
onComplete,
|
||
|
|
onLoadingChange,
|
||
|
|
setDisplayText,
|
||
|
|
}: UseCartPollingParams) {
|
||
|
|
const timeoutRef = useRef<number | null>(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!enabled) return;
|
||
|
|
|
||
|
|
let cancelled = false;
|
||
|
|
|
||
|
|
async function tick() {
|
||
|
|
try {
|
||
|
|
onLoadingChange(true);
|
||
|
|
|
||
|
|
const update = await getCartUpdates();
|
||
|
|
|
||
|
|
if (cancelled) return;
|
||
|
|
|
||
|
|
if (update.status === 'complete') {
|
||
|
|
onLoadingChange(false);
|
||
|
|
onComplete();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (update.status === 'waiting') {
|
||
|
|
setDisplayText('Брок бегает по супермаркету...')
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (update.status === 'clear') {
|
||
|
|
const nextProducts = update.payload?.chunk?.map(product => normalizeProductImage(product)) ?? [];
|
||
|
|
onProductsChange(nextProducts);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (update.status === 'data') {
|
||
|
|
const chunk = update.payload?.chunk?.map(product => normalizeProductImage(product)) ?? [];
|
||
|
|
|
||
|
|
onProductsChange(current => {
|
||
|
|
const next = [...current];
|
||
|
|
|
||
|
|
chunk.forEach(product => {
|
||
|
|
const index = next.findIndex(item => item.name === product.name);
|
||
|
|
|
||
|
|
if (index === -1) {
|
||
|
|
next.push(product);
|
||
|
|
} else {
|
||
|
|
next[index] = {
|
||
|
|
...next[index],
|
||
|
|
n: next[index].n + product.n,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
return next;
|
||
|
|
});
|
||
|
|
|
||
|
|
setDisplayText('Брок закинул пару товаров...')
|
||
|
|
}
|
||
|
|
timeoutRef.current = window.setTimeout(tick, 3000);
|
||
|
|
} catch (error) {
|
||
|
|
setDisplayText('Ищем Брока...')
|
||
|
|
timeoutRef.current = window.setTimeout(tick, 3000);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
tick();
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
cancelled = true;
|
||
|
|
|
||
|
|
if (timeoutRef.current) {
|
||
|
|
window.clearTimeout(timeoutRef.current);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}, [enabled, onComplete, onLoadingChange, onProductsChange]);
|
||
|
|
}
|