fix: remove landing page nav tab and prevent crowdsource contribution modal from auto-opening on tourism map
This commit is contained in:
@@ -8,7 +8,7 @@ import { LandmarkCard, HeritageLandmarkData } from './components/LandmarkCard';
|
|||||||
import { SubmitContributionModal } from './components/SubmitContributionModal';
|
import { SubmitContributionModal } from './components/SubmitContributionModal';
|
||||||
import { GuidesModerationPanel } from './components/GuidesModerationPanel';
|
import { GuidesModerationPanel } from './components/GuidesModerationPanel';
|
||||||
|
|
||||||
const DEFAULT_API_KEY = (import.meta as any).env.VITE_API_KEY || localStorage.getItem('intaleq_api_key') || '';
|
const DEFAULT_API_KEY = (import.meta as any).env.VITE_API_KEY || localStorage.getItem('intaleq_api_key') || localStorage.getItem('map_admin_key');
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [map, setMap] = useState<any>(null);
|
const [map, setMap] = useState<any>(null);
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { X, Send, MapPin, CheckCircle2, AlertCircle, Sparkles, Shield } from 'lu
|
|||||||
import { HeritageLandmarkData } from './LandmarkCard';
|
import { HeritageLandmarkData } from './LandmarkCard';
|
||||||
|
|
||||||
interface SubmitContributionModalProps {
|
interface SubmitContributionModalProps {
|
||||||
|
isOpen?: boolean;
|
||||||
landmark?: HeritageLandmarkData | null;
|
landmark?: HeritageLandmarkData | null;
|
||||||
|
initialLandmark?: HeritageLandmarkData | null;
|
||||||
mapCenter?: { lat: number; lng: number };
|
mapCenter?: { lat: number; lng: number };
|
||||||
apiKey?: string;
|
apiKey?: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -11,21 +13,46 @@ interface SubmitContributionModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = ({
|
export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = ({
|
||||||
|
isOpen = false,
|
||||||
landmark,
|
landmark,
|
||||||
|
initialLandmark,
|
||||||
mapCenter,
|
mapCenter,
|
||||||
apiKey = '',
|
apiKey = '',
|
||||||
onClose,
|
onClose,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
}) => {
|
}) => {
|
||||||
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
const targetLandmark = landmark || initialLandmark;
|
||||||
const [displayName, setDisplayName] = useState('المرشد الميداني (حمزة)');
|
const [displayName, setDisplayName] = useState('المرشد الميداني (حمزة)');
|
||||||
const [contributionType, setContributionType] = useState('CONFIRM_GATE');
|
const [contributionType, setContributionType] = useState('CONFIRM_GATE');
|
||||||
const [lat, setLat] = useState(landmark?.coordinates.access_gate?.lat ?? mapCenter?.lat ?? 31.9539);
|
const [lat, setLat] = useState(targetLandmark?.coordinates.access_gate?.lat ?? mapCenter?.lat ?? 31.9539);
|
||||||
const [lng, setLng] = useState(landmark?.coordinates.access_gate?.lng ?? mapCenter?.lng ?? 35.9106);
|
const [lng, setLng] = useState(targetLandmark?.coordinates.access_gate?.lng ?? mapCenter?.lng ?? 35.9106);
|
||||||
const [notes, setNotes] = useState('');
|
const [notes, setNotes] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [submitted, setSubmitted] = useState(false);
|
const [submitted, setSubmitted] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [onClose]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (targetLandmark?.coordinates.access_gate) {
|
||||||
|
setLat(targetLandmark.coordinates.access_gate.lat);
|
||||||
|
setLng(targetLandmark.coordinates.access_gate.lng);
|
||||||
|
} else if (mapCenter) {
|
||||||
|
setLat(mapCenter.lat);
|
||||||
|
setLng(mapCenter.lng);
|
||||||
|
}
|
||||||
|
}, [targetLandmark, mapCenter]);
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -38,8 +65,8 @@ export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = (
|
|||||||
displayName: displayName.trim(),
|
displayName: displayName.trim(),
|
||||||
contributionType,
|
contributionType,
|
||||||
targetTable: 'heritage.landmarks',
|
targetTable: 'heritage.landmarks',
|
||||||
targetId: landmark?.id ?? null,
|
targetId: targetLandmark?.id ?? null,
|
||||||
placeName: landmark?.name_ar || 'معلم أثري ميداني',
|
placeName: targetLandmark?.name_ar || 'معلم أثري ميداني',
|
||||||
lat: parseFloat(lat as any),
|
lat: parseFloat(lat as any),
|
||||||
lng: parseFloat(lng as any),
|
lng: parseFloat(lng as any),
|
||||||
suggestedData: {
|
suggestedData: {
|
||||||
@@ -75,6 +102,7 @@ export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = (
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
dir="rtl"
|
dir="rtl"
|
||||||
|
onClick={onClose}
|
||||||
style={{
|
style={{
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
inset: 0,
|
inset: 0,
|
||||||
@@ -89,6 +117,7 @@ export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = (
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
maxWidth: '520px',
|
maxWidth: '520px',
|
||||||
@@ -134,7 +163,7 @@ export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = (
|
|||||||
<Sparkles size={16} /> شبكة المساهمين والمرشدين المحليين
|
<Sparkles size={16} /> شبكة المساهمين والمرشدين المحليين
|
||||||
</div>
|
</div>
|
||||||
<h2 style={{ margin: 0, fontSize: '20px', fontWeight: 800 }}>
|
<h2 style={{ margin: 0, fontSize: '20px', fontWeight: 800 }}>
|
||||||
{landmark ? `اقتراح وتوثيق: ${landmark.name_ar}` : 'إضافة وتوثيق بوابة سياحية جديدة'}
|
{targetLandmark ? `اقتراح وتوثيق: ${targetLandmark.name_ar}` : 'إضافة وتوثيق بوابة سياحية جديدة'}
|
||||||
</h2>
|
</h2>
|
||||||
<p style={{ margin: '6px 0 0', fontSize: '13px', color: '#94a3b8' }}>
|
<p style={{ margin: '6px 0 0', fontSize: '13px', color: '#94a3b8' }}>
|
||||||
تخضع المساهمات لطابور المراجعة المعتمد قبل نشرها للجمهور وتمنحك نقاط المرشد الموثوق.
|
تخضع المساهمات لطابور المراجعة المعتمد قبل نشرها للجمهور وتمنحك نقاط المرشد الموثوق.
|
||||||
@@ -315,29 +344,48 @@ export const SubmitContributionModal: React.FC<SubmitContributionModalProps> = (
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Submit Button */}
|
{/* Submit & Cancel Buttons */}
|
||||||
<button
|
<div style={{ display: 'flex', gap: '10px', marginTop: '10px' }}>
|
||||||
type="submit"
|
<button
|
||||||
disabled={loading}
|
type="button"
|
||||||
style={{
|
onClick={onClose}
|
||||||
width: '100%',
|
style={{
|
||||||
background: 'linear-gradient(135deg, #0b2547 0%, #153e75 100%)',
|
flex: 1,
|
||||||
color: '#ffffff',
|
background: 'rgba(241, 245, 249, 0.9)',
|
||||||
border: 'none',
|
color: '#475569',
|
||||||
borderRadius: '12px',
|
border: '1px solid #cbd5e1',
|
||||||
padding: '14px',
|
borderRadius: '12px',
|
||||||
fontSize: '15px',
|
padding: '13px',
|
||||||
fontWeight: 800,
|
fontSize: '14px',
|
||||||
cursor: loading ? 'wait' : 'pointer',
|
fontWeight: 700,
|
||||||
display: 'flex',
|
cursor: 'pointer',
|
||||||
alignItems: 'center',
|
}}
|
||||||
justifyContent: 'center',
|
>
|
||||||
gap: '8px',
|
إلغاء
|
||||||
boxShadow: '0 4px 14px rgba(11, 37, 71, 0.25)',
|
</button>
|
||||||
}}
|
<button
|
||||||
>
|
type="submit"
|
||||||
{loading ? 'جارٍ الإرسال والتسجيل...' : <><Send size={16} /> إرسال المساهمة لطابور الاعتماد</>}
|
disabled={loading}
|
||||||
</button>
|
style={{
|
||||||
|
flex: 2,
|
||||||
|
background: 'linear-gradient(135deg, #0b2547 0%, #153e75 100%)',
|
||||||
|
color: '#ffffff',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '12px',
|
||||||
|
padding: '13px',
|
||||||
|
fontSize: '14px',
|
||||||
|
fontWeight: 800,
|
||||||
|
cursor: loading ? 'wait' : 'pointer',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: '8px',
|
||||||
|
boxShadow: '0 4px 14px rgba(11, 37, 71, 0.25)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{loading ? 'جارٍ الإرسال والتسجيل...' : <><Send size={16} /> إرسال المساهمة لطابور الاعتماد</>}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+137
-7
@@ -25,7 +25,6 @@ try {
|
|||||||
|
|
||||||
// Lightweight hash router with Sovereign Executive Styling
|
// Lightweight hash router with Sovereign Executive Styling
|
||||||
const NAV = [
|
const NAV = [
|
||||||
{ hash: '#landing', label: 'Landing Page (صفحة الهبوط)', icon: '🚀' },
|
|
||||||
{ hash: '#map', label: 'الخريطة والملاحة الشاملة', icon: '🗺️' },
|
{ hash: '#map', label: 'الخريطة والملاحة الشاملة', icon: '🗺️' },
|
||||||
{ hash: '#terrain3d', label: 'الخريطة ثلاثية الأبعاد والتضاريس', icon: '🏔️' },
|
{ hash: '#terrain3d', label: 'الخريطة ثلاثية الأبعاد والتضاريس', icon: '🏔️' },
|
||||||
{ hash: '#tourism', label: 'الخريطة السياحية والتراثية', icon: '🏛️' },
|
{ hash: '#tourism', label: 'الخريطة السياحية والتراثية', icon: '🏛️' },
|
||||||
@@ -37,13 +36,33 @@ const NAV = [
|
|||||||
function MasterHeader({ hash }: { hash: string }) {
|
function MasterHeader({ hash }: { hash: string }) {
|
||||||
const currentHash = hash || '#map'
|
const currentHash = hash || '#map'
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
const [showAdminModal, setShowAdminModal] = useState(false);
|
||||||
|
const [adminKey, setAdminKey] = useState(() => {
|
||||||
|
return (import.meta as any).env.VITE_ADMIN_API_KEY || (import.meta as any).env.VITE_API_KEY || localStorage.getItem('map_admin_key') || localStorage.getItem('intaleq_api_key') || '';
|
||||||
|
});
|
||||||
|
const [keyInput, setKeyInput] = useState(adminKey);
|
||||||
|
const [savedSuccess, setSavedSuccess] = useState(false);
|
||||||
|
|
||||||
|
const saveAdminKey = (newKey: string) => {
|
||||||
|
const trimmed = newKey.trim();
|
||||||
|
localStorage.setItem('map_admin_key', trimmed);
|
||||||
|
localStorage.setItem('intaleq_api_key', trimmed);
|
||||||
|
sessionStorage.setItem('tactical_api_key', trimmed);
|
||||||
|
setAdminKey(trimmed);
|
||||||
|
setSavedSuccess(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setSavedSuccess(false);
|
||||||
|
setShowAdminModal(false);
|
||||||
|
window.location.reload();
|
||||||
|
}, 800);
|
||||||
|
};
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = () => {
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
document.documentElement.requestFullscreen().catch(() => {});
|
document.documentElement.requestFullscreen().catch(() => { });
|
||||||
setIsFullscreen(true);
|
setIsFullscreen(true);
|
||||||
} else {
|
} else {
|
||||||
document.exitFullscreen().catch(() => {});
|
document.exitFullscreen().catch(() => { });
|
||||||
setIsFullscreen(false);
|
setIsFullscreen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -149,8 +168,29 @@ function MasterHeader({ hash }: { hash: string }) {
|
|||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Left Section: Live Sovereign Telemetry & Fullscreen */}
|
{/* Left Section: Admin Key Clearance & Telemetry & Fullscreen */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowAdminModal(true)}
|
||||||
|
title="تصريح المشرف الرسمي (Admin Clearance)"
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 6,
|
||||||
|
background: 'rgba(234, 179, 8, 0.12)',
|
||||||
|
border: '1px solid rgba(234, 179, 8, 0.35)',
|
||||||
|
color: '#facc15',
|
||||||
|
padding: '4px 10px',
|
||||||
|
borderRadius: 8,
|
||||||
|
fontSize: '0.72rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>🛡️</span>
|
||||||
|
<span>تصريح المشرف (Admin)</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -194,6 +234,99 @@ function MasterHeader({ hash }: { hash: string }) {
|
|||||||
<span>{isFullscreen ? '🗗' : '🗖'}</span>
|
<span>{isFullscreen ? '🗗' : '🗖'}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Admin Key Clearance Modal */}
|
||||||
|
{showAdminModal && (
|
||||||
|
<div style={{
|
||||||
|
position: 'fixed',
|
||||||
|
inset: 0,
|
||||||
|
background: 'rgba(0, 0, 0, 0.75)',
|
||||||
|
backdropFilter: 'blur(10px)',
|
||||||
|
zIndex: 100000,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
direction: 'rtl'
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
background: '#0d1527',
|
||||||
|
border: '1px solid rgba(234, 179, 8, 0.4)',
|
||||||
|
borderRadius: 16,
|
||||||
|
padding: '24px 28px',
|
||||||
|
width: 480,
|
||||||
|
maxWidth: '90vw',
|
||||||
|
boxShadow: '0 20px 50px rgba(0,0,0,0.6)',
|
||||||
|
color: '#fff'
|
||||||
|
}}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
|
||||||
|
<span style={{ fontSize: 24 }}>🛡️</span>
|
||||||
|
<h3 style={{ margin: 0, fontSize: '1.1rem', fontWeight: 800 }}>تصريح المشرف الرسمي (Admin Clearance)</h3>
|
||||||
|
</div>
|
||||||
|
<p style={{ fontSize: '0.85rem', color: '#94a3b8', margin: '0 0 16px 0', lineHeight: 1.6 }}>
|
||||||
|
يُستخدم هذا المفتاح للوصول إلى المنظومة التكتيكية وتدقيق الطرق الذكي وكافة ميزات المنصة السيادية بصلاحيات المشرف الكاملة.
|
||||||
|
</p>
|
||||||
|
<div style={{ marginBottom: 16 }}>
|
||||||
|
<label style={{ display: 'block', fontSize: '0.78rem', color: '#cbd5e1', marginBottom: 6, fontWeight: 700 }}>
|
||||||
|
مفتاح الـ API الرسمي للمشرف (Admin API Key):
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={keyInput}
|
||||||
|
onChange={(e) => setKeyInput(e.target.value)}
|
||||||
|
placeholder="أدخل مفتاح الـ Admin هنا..."
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '10px 14px',
|
||||||
|
borderRadius: 8,
|
||||||
|
border: '1px solid rgba(255, 255, 255, 0.15)',
|
||||||
|
background: 'rgba(255, 255, 255, 0.05)',
|
||||||
|
color: '#facc15',
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
outline: 'none',
|
||||||
|
boxSizing: 'border-box'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{savedSuccess && (
|
||||||
|
<div style={{ color: '#4ade80', fontSize: '0.82rem', marginBottom: 12, fontWeight: 700 }}>
|
||||||
|
✅ تم حفظ وتفعيل مفتاح المشرف بنجاح! جاري التحديث...
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowAdminModal(false)}
|
||||||
|
style={{
|
||||||
|
padding: '8px 16px',
|
||||||
|
borderRadius: 8,
|
||||||
|
border: '1px solid rgba(255, 255, 255, 0.15)',
|
||||||
|
background: 'transparent',
|
||||||
|
color: '#94a3b8',
|
||||||
|
cursor: 'pointer',
|
||||||
|
fontWeight: 600
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
إلغاء
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => saveAdminKey(keyInput)}
|
||||||
|
style={{
|
||||||
|
padding: '8px 20px',
|
||||||
|
borderRadius: 8,
|
||||||
|
border: 'none',
|
||||||
|
background: 'linear-gradient(135deg, #eab308, #ca8a04)',
|
||||||
|
color: '#000',
|
||||||
|
fontWeight: 800,
|
||||||
|
cursor: 'pointer',
|
||||||
|
boxShadow: '0 2px 10px rgba(234, 179, 8, 0.4)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
تفعيل وحفظ المفتاح
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -261,9 +394,6 @@ function Root() {
|
|||||||
return window.location.hash;
|
return window.location.hash;
|
||||||
}
|
}
|
||||||
const p = window.location.pathname.toLowerCase();
|
const p = window.location.pathname.toLowerCase();
|
||||||
if (p.includes('landing')) {
|
|
||||||
return '#landing';
|
|
||||||
}
|
|
||||||
if (p.includes('tourism') || p.includes('heritage') || p.includes('tourist') || window.location.href.includes('سياح')) {
|
if (p.includes('tourism') || p.includes('heritage') || p.includes('tourist') || window.location.href.includes('سياح')) {
|
||||||
return '#tourism';
|
return '#tourism';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ export const TourismMapView: React.FC = () => {
|
|||||||
startLat = fallbackHub[1];
|
startLat = fallbackHub[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const SOVEREIGN_MAP_API_KEY = 'zP9vL5mK2nQ8xR7jT4wS1yB6hG3fV0cX';
|
const SOVEREIGN_MAP_API_KEY = (import.meta as any).env.VITE_API_KEY || (import.meta as any).env.VITE_ADMIN_API_KEY || localStorage.getItem('map_admin_key') || localStorage.getItem('intaleq_api_key') || '';
|
||||||
const queryParams = `fromLat=${startLat}&fromLng=${startLng}&toLat=${lat}&toLng=${lng}&profile=car&steps=true&locale=ar&key=${SOVEREIGN_MAP_API_KEY}`;
|
const queryParams = `fromLat=${startLat}&fromLng=${startLng}&toLat=${lat}&toLng=${lng}&profile=car&steps=true&locale=ar&key=${SOVEREIGN_MAP_API_KEY}`;
|
||||||
|
|
||||||
const isServerEnv = window.location.hostname.includes('intaleqapp.com') || window.location.port === '3201' || window.location.port === '3204';
|
const isServerEnv = window.location.hostname.includes('intaleqapp.com') || window.location.port === '3201' || window.location.port === '3204';
|
||||||
@@ -1000,12 +1000,18 @@ export const TourismMapView: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 7. Crowdsourcing Contribution Modal */}
|
{/* 7. Crowdsourcing Contribution Modal (Only open on user action) */}
|
||||||
<SubmitContributionModal
|
{isContributeOpen && (
|
||||||
isOpen={isContributeOpen}
|
<SubmitContributionModal
|
||||||
onClose={() => setIsContributeOpen(false)}
|
isOpen={isContributeOpen}
|
||||||
initialLandmark={contributeTarget}
|
onClose={() => {
|
||||||
/>
|
setIsContributeOpen(false);
|
||||||
|
setContributeTarget(undefined);
|
||||||
|
}}
|
||||||
|
initialLandmark={contributeTarget}
|
||||||
|
mapCenter={mapInstance ? { lat: mapInstance.getCenter().lat, lng: mapInstance.getCenter().lng } : undefined}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 8. Sovereign In-App Navigation HUD */}
|
{/* 8. Sovereign In-App Navigation HUD */}
|
||||||
{activeNav && (
|
{activeNav && (
|
||||||
|
|||||||
Reference in New Issue
Block a user