diff --git a/src/hooks/useAdminStats.js b/src/hooks/useAdminStats.js index 3299fc1..ef18773 100644 --- a/src/hooks/useAdminStats.js +++ b/src/hooks/useAdminStats.js @@ -1,13 +1,13 @@ import { useState, useEffect, useCallback } from "react"; +import { supabase, hasSupabaseConfig } from "../supabaseClient"; const PERIOD_DAYS = { today: 1, "7d": 7, "30d": 30, all: 0 }; const rpcCall = async (fnName, params) => { - const { createClient } = await import("@supabase/supabase-js"); - const supabaseUrl = window.__SUPABASE_URL__ || import.meta.env.VITE_SUPABASE_URL; - const supabaseAnonKey = window.__SUPABASE_ANON_KEY__ || import.meta.env.VITE_SUPABASE_ANON_KEY; - const client = createClient(supabaseUrl, supabaseAnonKey); - const { data, error } = await client.rpc(fnName, params); + if (!hasSupabaseConfig || !supabase) { + throw new Error("Supabase не сконфигурирован"); + } + const { data, error } = await supabase.rpc(fnName, params); if (error) throw error; return data; }; diff --git a/src/utils/errorLogger.js b/src/utils/errorLogger.js index 3160d2d..994c0ba 100644 --- a/src/utils/errorLogger.js +++ b/src/utils/errorLogger.js @@ -1,25 +1,27 @@ -import { createClient } from '@supabase/supabase-js'; - -const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; -const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY; - -const supabase = createClient(supabaseUrl, supabaseAnonKey); +import { supabase, hasSupabaseConfig } from "../supabaseClient"; // Debounce tracking: message -> last timestamp const recentErrors = new Map(); const DEBOUNCE_MS = 10000; function getUserId() { - // Try to get from Supabase auth session in localStorage + // Try to get from Supabase auth session in sessionStorage try { - const keys = Object.keys(localStorage); + const keys = Object.keys(sessionStorage); const authKey = keys.find( - (k) => k.startsWith('sb-') && k.endsWith('-auth-token') + (k) => k.startsWith("sb-") && k.endsWith("-auth-token") ); if (authKey) { - const data = JSON.parse(localStorage.getItem(authKey)); + const data = JSON.parse(sessionStorage.getItem(authKey)); return data?.user?.id || null; } + // Also check supersam secure storage format + const ssKey = keys.find((k) => k === "supersam-auth"); + if (ssKey) { + const data = JSON.parse(sessionStorage.getItem(ssKey)); + // The secure storage obfuscates values, but the key structure is known + // Fall through to window.__supersam_user_id__ set by AuthContext + } } catch { // ignore } @@ -46,19 +48,20 @@ function isDebounced(message) { async function insertErrorLog(entry) { try { - await supabase.from('client_error_logs').insert([entry]); + if (!hasSupabaseConfig || !supabase) return; + await supabase.from("client_error_logs").insert([entry]); } catch { // Fire-and-forget — swallow insertion errors } } function logError(error, componentInfo) { - if (!(error instanceof Error) && typeof error !== 'object' && typeof error !== 'string') { + if (!(error instanceof Error) && typeof error !== "object" && typeof error !== "string") { return; } const message = - typeof error === 'string' + typeof error === "string" ? error : error?.message || String(error); @@ -66,7 +69,7 @@ function logError(error, componentInfo) { if (isDebounced(message)) return; const stack = - typeof error === 'object' && error !== null ? error.stack || null : null; + typeof error === "object" && error !== null ? error.stack || null : null; let line_number = null; let column_number = null; @@ -83,16 +86,16 @@ function logError(error, componentInfo) { } const entry = { - user_id: getUserId(), + user_id: getUserId() || window.__supersam_user_id__ || null, message, stack, url, line_number, column_number, error_type: - typeof error === 'object' && error !== null - ? error.constructor?.name || 'Error' - : 'String', + typeof error === "object" && error !== null + ? error.constructor?.name || "Error" + : "String", component: componentInfo?.component || null, props: componentInfo?.props ? JSON.stringify(componentInfo.props) @@ -106,16 +109,14 @@ function logError(error, componentInfo) { } function initErrorLogging(userId) { - // If a userId is provided, override the getUserId logic + // If a userId is provided, store it for future logError calls if (userId) { - const origGetUserId = getUserId; - // We store it so future logError calls can use it window.__supersam_user_id__ = userId; } // Catch synchronous errors window.onerror = function (message, source, lineno, colno, error) { - const msg = typeof message === 'string' ? message : String(message); + const msg = typeof message === "string" ? message : String(message); if (isDebounced(msg)) return; @@ -126,7 +127,7 @@ function initErrorLogging(userId) { url: source || null, line_number: lineno || null, column_number: colno || null, - error_type: error?.constructor?.name || 'Error', + error_type: error?.constructor?.name || "Error", component: null, props: null, user_agent: navigator.userAgent, @@ -142,7 +143,7 @@ function initErrorLogging(userId) { const message = error instanceof Error ? error.message - : typeof error === 'string' + : typeof error === "string" ? error : String(error); @@ -170,8 +171,8 @@ function initErrorLogging(userId) { column_number, error_type: error instanceof Error - ? error.constructor?.name || 'Error' - : 'UnhandledRejection', + ? error.constructor?.name || "Error" + : "UnhandledRejection", component: null, props: null, user_agent: navigator.userAgent,