diff --git a/components/sections/Faq.tsx b/components/sections/Faq.tsx index 245dc32..2927f46 100644 --- a/components/sections/Faq.tsx +++ b/components/sections/Faq.tsx @@ -25,10 +25,13 @@ export async function FAQ({ lang: string; }) { let faqs: PBFaq[] = []; + // Различаем "PocketBase ответил, но для этого языка коллекции ещё нет" (штатно, + // это и есть fallback на en ниже) от "PocketBase вообще не ответил ни разу" — + // раньше оба случая одинаково показывали "0 protocols found", что вводит в + // заблуждение при реальном сбое инфраструктуры (выглядит как "у нас нет FAQ", + // а не "сейчас не грузится"). + let hadFetchError = false; - // CMS-контент (в отличие от статичных dictionaries/*.json) переведён только - // для части языков — коллекции `faqs_` для новых языков ещё не заведены - // в PocketBase. Пока для них нет перевода, показываем английский, а не пустоту. for (const fallbackLang of Array.from(new Set([lang, "en"]))) { try { faqs = await pb.collection(`faqs_${fallbackLang}`).getFullList({ @@ -36,8 +39,10 @@ export async function FAQ({ fetch: (url, config) => fetch(url, { ...config, next: { revalidate: 86400 } }), // Кэшируем на сутки }); + hadFetchError = false; break; } catch (error) { + hadFetchError = true; console.error(`Ошибка загрузки FAQ (${fallbackLang}):`, error); } } @@ -88,7 +93,7 @@ export async function FAQ({ {faqs.length === 0 ? (

- 0 protocols found in cache. + {hadFetchError ? dict.loadError : "0 protocols found in cache."}

) : ( diff --git a/components/sections/Pricing.tsx b/components/sections/Pricing.tsx index 177612a..78084d3 100644 --- a/components/sections/Pricing.tsx +++ b/components/sections/Pricing.tsx @@ -63,9 +63,14 @@ export function Pricing({ const [period, setPeriod] = useState("1y"); const [plans, setPlans] = useState([]); const [loading, setLoading] = useState(!!lang); + // PocketBase недоступен целиком (не просто нет перевода для этого языка) — + // показываем последний успешно закэшированный список вместо пустой секции. + const [usingCache, setUsingCache] = useState(false); useEffect(() => { if (!lang) return; + const cacheKey = `netrunner_pricing_cache_${lang}`; + async function fetchPlans() { try { setLoading(true); @@ -74,6 +79,7 @@ export function Pricing({ // `pricing_` для новых языков ещё не заведена в PocketBase. // Пока для них нет перевода, показываем английские тарифы, а не пустоту. let records: PBPricingPlan[] = []; + let allFailed = true; for (const fallbackLang of Array.from(new Set([lang, "en"]))) { try { records = await pb @@ -82,11 +88,34 @@ export function Pricing({ sort: "order", requestKey: null, }); + allFailed = false; break; } catch (error) { console.error(`Ошибка загрузки тарифов (${fallbackLang}):`, error); } } + + if (allFailed) { + try { + const cached = localStorage.getItem(cacheKey); + if (cached) { + records = JSON.parse(cached); + setUsingCache(true); + } + } catch { + // localStorage недоступен (приватный режим и т.п.) — просто нет кеша. + } + } else { + setUsingCache(false); + if (records.length > 0) { + try { + localStorage.setItem(cacheKey, JSON.stringify(records)); + } catch { + // Диск/квота localStorage — не критично, просто не кешируем. + } + } + } + setPlans(records); } finally { setLoading(false); @@ -121,10 +150,16 @@ export function Pricing({ > {dict.badge} -

+

{dict.title}

+ {usingCache && ( +

+ {dict.offlineNotice} +

+ )} +
{periods.map((p: PeriodOption) => (