This commit is contained in:
@ -105,7 +105,6 @@
|
||||
// }
|
||||
|
||||
|
||||
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
@ -118,9 +117,108 @@ const ENDPOINTS = {
|
||||
en: '/Configuration/GetENPrivacyPolicy',
|
||||
};
|
||||
|
||||
function tryParseJson(value) {
|
||||
let current = value;
|
||||
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
if (typeof current !== 'string') break;
|
||||
|
||||
const trimmed = current.trim();
|
||||
if (!trimmed) return trimmed;
|
||||
|
||||
try {
|
||||
current = JSON.parse(trimmed);
|
||||
} catch {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
function normalizeItem(item, index) {
|
||||
if (!item || typeof item !== 'object') return null;
|
||||
|
||||
const title =
|
||||
typeof item.title === 'string' ? item.title.trim() : '';
|
||||
const description =
|
||||
typeof item.description === 'string' ? item.description.trim() : '';
|
||||
|
||||
if (!title && !description) return null;
|
||||
|
||||
return {
|
||||
id: index + 1,
|
||||
title,
|
||||
description,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizePolicyContent(raw) {
|
||||
const decoded = tryParseJson(raw);
|
||||
|
||||
if (Array.isArray(decoded)) {
|
||||
const items = decoded.map((item, index) => normalizeItem(item, index)).filter(Boolean);
|
||||
return {
|
||||
items,
|
||||
rawText: typeof raw === 'string' ? raw.trim() : '',
|
||||
};
|
||||
}
|
||||
|
||||
if (decoded && typeof decoded === 'object') {
|
||||
const possibleArray = Array.isArray(decoded.items)
|
||||
? decoded.items
|
||||
: Array.isArray(decoded.data)
|
||||
? decoded.data
|
||||
: null;
|
||||
|
||||
if (possibleArray) {
|
||||
const items = possibleArray.map((item, index) => normalizeItem(item, index)).filter(Boolean);
|
||||
return {
|
||||
items,
|
||||
rawText: typeof raw === 'string' ? raw.trim() : '',
|
||||
};
|
||||
}
|
||||
|
||||
const singleItem = normalizeItem(decoded, 0);
|
||||
if (singleItem) {
|
||||
return {
|
||||
items: [singleItem],
|
||||
rawText: typeof raw === 'string' ? raw.trim() : '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof decoded === 'string') {
|
||||
const cleaned = decoded.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n').trim();
|
||||
|
||||
const matches = [...cleaned.matchAll(/"title"\s*:\s*"([^"]+)"\s*,\s*"description"\s*:\s*"([^"]+)"/g)];
|
||||
if (matches.length > 0) {
|
||||
return {
|
||||
items: matches.map((match, index) => ({
|
||||
id: index + 1,
|
||||
title: match[1].trim(),
|
||||
description: match[2].trim(),
|
||||
})),
|
||||
rawText: cleaned,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
items: [],
|
||||
rawText: cleaned,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
items: [],
|
||||
rawText: '',
|
||||
};
|
||||
}
|
||||
|
||||
export default function PrivacyPage() {
|
||||
const [language, setLanguage] = useState('ar');
|
||||
const [policyText, setPolicyText] = useState('');
|
||||
const [policyItems, setPolicyItems] = useState([]);
|
||||
const [rawPolicyText, setRawPolicyText] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@ -146,13 +244,14 @@ export default function PrivacyPage() {
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
const normalized = normalizePolicyContent(text);
|
||||
|
||||
console.log('API RESPONSE:', text);
|
||||
|
||||
setPolicyText(text.trim());
|
||||
setPolicyItems(normalized.items);
|
||||
setRawPolicyText(normalized.rawText);
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
setPolicyText('');
|
||||
if (err?.name !== 'AbortError') {
|
||||
setPolicyItems([]);
|
||||
setRawPolicyText('');
|
||||
setError(
|
||||
language === 'ar'
|
||||
? 'تعذر تحميل النص من الخادم.'
|
||||
@ -207,9 +306,37 @@ export default function PrivacyPage() {
|
||||
)}
|
||||
|
||||
<div className="rounded-2xl border border-gray-200 bg-white p-6 shadow-sm">
|
||||
<div className="whitespace-pre-wrap leading-8 text-gray-800">
|
||||
{policyText}
|
||||
</div>
|
||||
{policyItems.length > 0 ? (
|
||||
<div className="space-y-4">
|
||||
{policyItems.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="rounded-2xl border border-gray-200 bg-gray-50 p-5"
|
||||
>
|
||||
{item.title && (
|
||||
<div className="mb-3 flex items-start gap-3">
|
||||
<div className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-amber-100 text-sm font-bold text-amber-700">
|
||||
{item.id}
|
||||
</div>
|
||||
<h3 className="text-base font-bold text-gray-900">
|
||||
{item.title}
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{item.description && (
|
||||
<p className="text-sm leading-8 text-gray-700 whitespace-pre-wrap">
|
||||
{item.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="whitespace-pre-wrap leading-8 text-gray-800">
|
||||
{rawPolicyText}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user