PageSourceSearch

https://proparcel.com/static/js/app/ui/pro_query_verification_modal.js

js proparcel.com collected 2026-09-24 14:52:38 UTC 11,740 bytes, 271 lines download raw bytes

1/**
2 * VIP Doğrulama modalı — konum + arsa/tarla/ticari verified durumu.
3 * ESC / backdrop kapatmaz; İptal → false, Devam → true.
4 */
5
6function pickValue(source, keys) {
7  try {
8    for (let i = 0; i < keys.length; i++) {
9      const k = keys[i];
10      const v = source ? source[k] : null;
11      if (v !== null && v !== undefined && String(v).trim() !== '') return String(v).trim();
12    }
13  } catch (_) {}
14  return '';
15}
16
17function formatArea(value) {
18  if (value === null || value === undefined || value === '') return '';
19  try {
20    if (typeof window.formatAreaM2Label === 'function') {
21      const t = window.formatAreaM2Label(value);
22      if (t) return t;
23    }
24    if (typeof window.parseLocaleNumberTr === 'function') {
25      const nTr = window.parseLocaleNumberTr(value);
26      if (Number.isFinite(nTr) && nTr > 0) {
27        return `${nTr.toLocaleString('tr-TR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })} m²`;
28      }
29    }
30  } catch (_) {}
31  return '';
32}
33
34function getCsrfToken() {
35  try {
36    const m = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
37    return m ? decodeURIComponent(m[1]) : '';
38  } catch (_) {
39    return '';
40  }
41}
42
43function statusLabel(status) {
44  const s = String(status || '').toLowerCase();
45  if (s === 'verified') return { text: 'Doğrulandı', color: '#15803d', bg: '#dcfce7', border: '#86efac' };
46  if (s === 'unverified') return { text: 'Doğrulanmadı', color: '#c2410c', bg: '#ffedd5', border: '#fdba74' };
47  return { text: 'Veri yok', color: '#475569', bg: '#f1f5f9', border: '#cbd5e1' };
48}
49
50function buildStatusRowHtml(label, status) {
51  const st = statusLabel(status);
52  return (
53    `<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border:1px solid #e2e8f0;background:#fff;margin-bottom:6px;">`
54    + `<span style="font-weight:700;color:#0f172a;font-size:13px;">${label}</span>`
55    + `<span style="font-weight:700;font-size:12px;padding:4px 10px;border:1px solid ${st.border};background:${st.bg};color:${st.color};">${st.text}</span>`
56    + `</div>`
57  );
58}
59
60async function fetchVerificationStatus(tkgmData) {
61  const props = (tkgmData && tkgmData.properties) ? tkgmData.properties : {};
62  const payload = {
63    proparcel_value: props.Proparcel_value ?? props.proparcel_value ?? null,
64    mahalleId: props.mahalleId ?? props.mahalleTkgmValue ?? props.mahalle_tkgm_value ?? null,
65    properties: {
66      Proparcel_value: props.Proparcel_value ?? props.proparcel_value ?? null,
67      mahalleId: props.mahalleId ?? null,
68      mahalleAd: props.mahalleAd ?? props.mahalle ?? null,
69      ilAd: props.ilAd ?? props.il ?? null,
70      ilceAd: props.ilceAd ?? props.ilce ?? null,
71    },
72  };
73
74  const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
75  const csrf = getCsrfToken();
76  if (csrf) headers['X-CSRFToken'] = csrf;
77
78  const res = await fetch('/api/quarter_price_verification_status/', {
79    method: 'POST',
80    credentials: 'same-origin',
81    headers,
82    body: JSON.stringify(payload),
83  });
84  const data = await res.json().catch(() => ({}));
85  if (!res.ok || !data || data.success !== true) {
86    throw new Error((data && data.error) || 'Durum alınamadı');
87  }
88  return data;
89}
90
91export function openProQueryVerificationModal(tkgmData) {
92  return new Promise((resolve) => {
93    try {
94      const existing = document.getElementById('ppProVerificationModal');
95      if (existing) existing.remove();
96    } catch (_) {}
97
98    const loadingSnapshot = (function () {
99      const snap = {
100        legacyVisible: false,
101        legacyText: null,
102      };
103      try {
104        const el = document.getElementById('loading-overlay');
105        if (el) {
106          const disp = String(el.style.display || '').toLowerCase();
107          snap.legacyVisible = disp !== 'none';
108          try {
109            const t = el.querySelector('div:last-child');
110            if (t && t.textContent) snap.legacyText = String(t.textContent);
111          } catch (_) {}
112        }
113      } catch (_) {}
114      return snap;
115    })();
116
117    try {
118      if (window.ProParcelLoader && typeof window.ProParcelLoader.isVisible === 'function' && window.ProParcelLoader.isVisible()) {
119        // leave animated loader
120      } else if (window.proParcelApp && typeof window.proParcelApp.hideLoading === 'function') {
121        window.proParcelApp.hideLoading();
122      } else if (typeof window.hideLoading === 'function') {
123        window.hideLoading();
124      } else {
125        const el = document.getElementById('loading-overlay');
126        if (el) el.style.display = 'none';
127      }
128    } catch (_) {}
129
130    const props = (tkgmData && tkgmData.properties) ? tkgmData.properties : {};
131    const il = pickValue(props, ['ilAd', 'il', 'cityName', 'CityName']);
132    const ilce = pickValue(props, ['ilceAd', 'ilce', 'townName', 'TownName']);
133    const mahalle = pickValue(props, ['mahalleAd', 'mahalle', 'quarterName', 'QuarterName']);
134    const ada = pickValue(props, ['adaNo', 'ada', 'Ada']);
135    const parsel = pickValue(props, ['parselNo', 'parsel', 'Parsel']);
136    const alanRaw =
137      (props ? (props.alan ?? props.yuzolcum ?? props.Yuzolcum ?? props.area ?? props.Area ?? props.area_m2) : null) ??
138      (tkgmData ? (tkgmData.alan ?? tkgmData.yuzolcum ?? tkgmData.Area) : null);
139    const alan = formatArea(alanRaw);
140    const row1 = [il, ilce, mahalle].filter(Boolean).join(' / ') || '-';
141    const row2Left = (ada && parsel) ? `${ada}/${parsel}` : (ada || parsel || '');
142    const row2 = [row2Left, alan].filter(Boolean).join(' • ') || '-';
143
144    const overlay = document.createElement('div');
145    overlay.id = 'ppProVerificationModal';
146    overlay.style.position = 'fixed';
147    overlay.style.left = '0';
148    overlay.style.top = '0';
149    overlay.style.width = '100%';
150    overlay.style.height = '100%';
151    overlay.style.background = 'transparent';
152    overlay.style.zIndex = '100001';
153
154    overlay.innerHTML = `
155<div id="ppProVerificationDialog" style="position:absolute;right:24px;top:50%;transform:translateY(-50%);background:#fff;border-radius:0;min-width:360px;max-width:92vw;box-shadow:0 12px 32px rgba(0,0,0,0.35);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
156  <div id="ppProVerificationHeader" style="padding:18px 22px 10px 22px;border-bottom:1px solid #eee;cursor:move;user-select:none;">
157    <div style="font-weight:800;color:#0f172a;font-size:16px;margin-bottom:8px;">Doğrulama Durumu</div>
158    <div style="font-weight:600;color:#334155;line-height:1.45;font-size:13.5px;white-space:pre-line;">${row1}</div>
159    <div style="font-weight:600;color:#334155;line-height:1.45;font-size:13.5px;white-space:pre-line;margin-top:4px;">${row2}</div>
160  </div>
161  <div style="padding:14px 22px 6px 22px;">
162    <div id="ppProVerificationStatusBody" style="background:#f8fafc;border:1px solid #e2e8f0;padding:12px;">
163      <div style="font-weight:600;color:#64748b;font-size:13px;">Kontrol ediliyor…</div>
164    </div>
165  </div>
166  <div style="padding:12px 22px 18px 22px;display:flex;gap:10px;justify-content:space-between;">
167    <button id="ppProVerificationCancel" class="btn" style="flex:1;border:1px solid #cbd5e1;background:#f1f5f9;border-radius:0;padding:10px 12px;font-weight:800;color:#334155;">İptal</button>
168    <button id="ppProVerificationOk" class="btn btn-primary" style="flex:1;border:1px solid #2563eb;background:#3b82f6;border-radius:0;padding:10px 12px;font-weight:800;color:#fff;">Devam</button>
169  </div>
170</div>`;
171
172    const cleanup = () => {
173      try { overlay.remove(); } catch (_) {}
174      try { document.removeEventListener('keydown', onKeyDown, { capture: true }); } catch (_) {}
175      try { document.removeEventListener('mousemove', onMove, true); } catch (_) {}
176      try { document.removeEventListener('mouseup', onUp, true); } catch (_) {}
177      try {
178        if (window.ProParcelLoader && typeof window.ProParcelLoader.isVisible === 'function' && window.ProParcelLoader.isVisible()) {
179          // keep
180        } else if (loadingSnapshot.legacyVisible) {
181          const msg = loadingSnapshot.legacyText || 'Parsel sorgulanıyor...';
182          if (window.proParcelApp && typeof window.proParcelApp.showLoading === 'function') {
183            window.proParcelApp.showLoading(msg);
184          } else if (typeof window.showLoading === 'function') {
185            window.showLoading(msg);
186          } else {
187            const el = document.getElementById('loading-overlay');
188            if (el) el.style.display = 'flex';
189          }
190        }
191      } catch (_) {}
192    };
193
194    const onKeyDown = (ev) => {
195      if (ev && ev.key === 'Escape') return;
196    };
197
198    const onClick = (ev) => {
199      const t = ev && ev.target;
200      if (!t) return;
201      if (t.id === 'ppProVerificationCancel') {
202        cleanup();
203        resolve(false);
204        return;
205      }
206      if (t.id === 'ppProVerificationOk') {
207        cleanup();
208        resolve(true);
209        return;
210      }
211    };
212
213    overlay.addEventListener('click', onClick, false);
214    document.addEventListener('keydown', onKeyDown, { capture: true });
215    document.body.appendChild(overlay);
216
217    const dialog = overlay.querySelector('#ppProVerificationDialog');
218    const header = overlay.querySelector('#ppProVerificationHeader');
219    const drag = { active: false, startX: 0, startY: 0, origLeft: 0, origTop: 0 };
220    const onMove = (ev) => {
221      if (!drag.active || !dialog) return;
222      const dx = ev.clientX - drag.startX;
223      const dy = ev.clientY - drag.startY;
224      dialog.style.left = `${drag.origLeft + dx}px`;
225      dialog.style.top = `${drag.origTop + dy}px`;
226    };
227    const onUp = () => {
228      drag.active = false;
229      try { document.removeEventListener('mousemove', onMove, true); } catch (_) {}
230      try { document.removeEventListener('mouseup', onUp, true); } catch (_) {}
231    };
232    if (header && dialog) {
233      header.addEventListener('mousedown', (ev) => {
234        if (ev.button !== 0) return;
235        ev.preventDefault();
236        drag.active = true;
237        drag.startX = ev.clientX;
238        drag.startY = ev.clientY;
239        const rect = dialog.getBoundingClientRect();
240        dialog.style.position = 'fixed';
241        dialog.style.transform = 'none';
242        dialog.style.left = `${rect.left}px`;
243        dialog.style.top = `${rect.top}px`;
244        drag.origLeft = rect.left;
245        drag.origTop = rect.top;
246        document.addEventListener('mousemove', onMove, true);
247        document.addEventListener('mouseup', onUp, true);
248      }, false);
249    }
250
251    const bodyEl = overlay.querySelector('#ppProVerificationStatusBody');
252    fetchVerificationStatus(tkgmData)
253      .then((data) => {
254        if (!bodyEl) return;
255        const p = (data && data.properties) || {};
256        const arsa = (p.arsa && p.arsa.status) || 'missing';
257        const tarla = (p.tarla && p.tarla.status) || 'missing';
258        const ticari = (p.ticari && p.ticari.status) || 'missing';
259        bodyEl.innerHTML =
260          `<div style="font-weight:700;color:#0f172a;font-size:13px;margin-bottom:10px;">Mahalle birim fiyat durumu</div>`
261          + buildStatusRowHtml('Arsa', arsa)
262          + buildStatusRowHtml('Tarla', tarla)
263          + buildStatusRowHtml('Ticari', ticari);
264      })
265      .catch(() => {
266        if (!bodyEl) return;
267        bodyEl.innerHTML =
268          `<div style="font-weight:600;color:#b45309;font-size:13px;line-height:1.45;">Durum alınamadı. İsterseniz yine de devam edebilirsiniz.</div>`;
269      });
270  });
271}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.