mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 03:41:25 +02:00
Projects included: - maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing) - manacore (Expo mobile + SvelteKit web + Astro landing) - manadeck (NestJS backend + Expo mobile + SvelteKit web) - memoro (Expo mobile + SvelteKit web + Astro landing) This commit preserves the current state before monorepo restructuring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
88 lines
No EOL
2.8 KiB
TypeScript
88 lines
No EOL
2.8 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { parseInsufficientCreditsError } from '../utils/insufficient-credits-handler';
|
|
import { useInsufficientCreditsStore } from '../store/insufficientCreditsStore';
|
|
|
|
interface InsufficientCreditsState {
|
|
isVisible: boolean;
|
|
requiredCredits?: number;
|
|
availableCredits?: number;
|
|
operation?: string;
|
|
}
|
|
|
|
/**
|
|
* Hook that intercepts HTTP 402 errors and manages the insufficient credits modal state
|
|
*/
|
|
export function useInsufficientCreditsInterceptor() {
|
|
const [modalState, setModalState] = useState<InsufficientCreditsState>({
|
|
isVisible: false
|
|
});
|
|
const setGlobalModalVisible = useInsufficientCreditsStore((state) => state.setModalVisible);
|
|
|
|
useEffect(() => {
|
|
// Store the original fetch
|
|
const originalFetch = global.fetch;
|
|
|
|
// Override global fetch to intercept responses
|
|
global.fetch = async (...args) => {
|
|
try {
|
|
const response = await originalFetch(...args);
|
|
|
|
// Check for 402 Payment Required status
|
|
if (response.status === 402) {
|
|
try {
|
|
// Clone response to read body without consuming it
|
|
const clonedResponse = response.clone();
|
|
const errorData = await clonedResponse.json();
|
|
|
|
console.debug('[InsufficientCreditsInterceptor] 402 error detected:', errorData);
|
|
|
|
// Parse the error to extract credit information
|
|
const creditInfo = parseInsufficientCreditsError(errorData);
|
|
|
|
// Show the modal with parsed information
|
|
// Add small delay to ensure this modal shows first
|
|
setTimeout(() => {
|
|
setModalState({
|
|
isVisible: true,
|
|
requiredCredits: creditInfo.requiredCredits,
|
|
availableCredits: creditInfo.availableCredits,
|
|
operation: creditInfo.operation
|
|
});
|
|
setGlobalModalVisible(true);
|
|
}, 100);
|
|
} catch (parseError) {
|
|
console.error('[InsufficientCreditsInterceptor] Error parsing 402 response:', parseError);
|
|
// Show modal with default message if parsing fails
|
|
setTimeout(() => {
|
|
setModalState({ isVisible: true });
|
|
setGlobalModalVisible(true);
|
|
}, 100);
|
|
}
|
|
}
|
|
|
|
return response;
|
|
} catch (error) {
|
|
// Network errors, etc.
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
// Cleanup on unmount
|
|
return () => {
|
|
global.fetch = originalFetch;
|
|
};
|
|
}, []);
|
|
|
|
const closeModal = () => {
|
|
setModalState({ isVisible: false });
|
|
setGlobalModalVisible(false);
|
|
};
|
|
|
|
return {
|
|
modalVisible: modalState.isVisible,
|
|
requiredCredits: modalState.requiredCredits,
|
|
availableCredits: modalState.availableCredits,
|
|
operation: modalState.operation,
|
|
closeModal
|
|
};
|
|
} |