Show tender source changes against saved preparation metadata
This commit is contained in:
@@ -105,6 +105,11 @@ export const TenderDetailModal = () => {
|
||||
<div ref={dialogRef} role="dialog" aria-modal="true" aria-labelledby={dialogTitleId} tabIndex={-1} onKeyDown={handleDialogKey} className="bg-white w-full max-w-6xl rounded-2xl shadow-2xl border border-slate-200 overflow-hidden my-auto flex flex-col max-h-[92vh]">
|
||||
|
||||
{(actionError || saveError) && <p role="alert" className="p-3 bg-red-50 text-red-900">{actionError || saveError}</p>}
|
||||
{tender.sourceChanges?.length > 0 && <div role="alert" className="p-3 bg-amber-50 text-amber-900 text-sm">
|
||||
<p className="font-bold">Son kaydettiğiniz bilgilere göre ihale değişmiş</p>
|
||||
<ul className="list-disc pl-5">{tender.sourceChanges.map(change => <li key={change.field}>{change.label}: {change.before} → {change.after}</li>)}</ul>
|
||||
<p>Takip, not ve hazırlık kayıtlarınız korundu. Yeni koşulları resmi kaynakla karşılaştırın.</p>
|
||||
</div>}
|
||||
{tender.sourceWarning && <p role="alert" className="p-3 bg-amber-50 text-amber-900 text-sm">{tender.sourceWarning}</p>}
|
||||
{detailLoad?.id === tender.id && detailLoad.status === 'loading' && <p role="status" className="p-3 bg-blue-50 text-blue-900">Kaynak ilan metni yükleniyor…</p>}
|
||||
{detailLoad?.id === tender.id && detailLoad.status === 'error' && <div role="alert" className="p-3 bg-amber-50 text-amber-900 text-sm">
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getToken } from '../services/auth';
|
||||
import { fetchLiveTenders, fetchTenderDetail, mergeUserState } from '../services/tenderApi';
|
||||
import { restoreSession, clearSession, getStoredUser } from '../services/auth';
|
||||
import { getAllUserData, setUserData, getPlan, bildirimleriGetir, bildirimOkundu, listDocuments } from '../services/account';
|
||||
import { applyTenderStates, tenderStateKey, tenderSnapshot, publicTender } from '../services/tenderState';
|
||||
import { applyTenderStates, tenderStateKey, tenderSnapshot, publicTender, tenderSourceChanges } from '../services/tenderState';
|
||||
import { getTenderStates, saveTenderState } from '../services/account';
|
||||
import { SECTORS_LIST, INSTITUTION_TYPES_LIST } from '../data/constants';
|
||||
|
||||
@@ -310,6 +310,7 @@ export const AppProvider = ({ children }) => {
|
||||
.then(detail => {
|
||||
if (cancelled) return;
|
||||
const source = publicTender(detail);
|
||||
source.sourceChanges = tenderSourceChanges(savedTenderStates.current[tenderStateKey(t)]?.snapshot, {...t,...source});
|
||||
setDetailLoad({id:t.id,status:'loaded'});
|
||||
setActiveTenderDetail(prev =>
|
||||
prev && prev.id === t.id ? { ...prev, ...source } : prev
|
||||
|
||||
@@ -32,6 +32,7 @@ export function bidSourceSnapshot(tender, results, rows = sourceRows(tender, res
|
||||
tender: tender?.ikn || tender?.id,
|
||||
announcement: tender?.aciklama || '',
|
||||
deadline: [tender?.tarih || '', tender?.saat || ''],
|
||||
status: tender?.durum || '',
|
||||
documentVersion: results?.documentVersion ?? tender?.documentVersion ?? null,
|
||||
procurementTerms: results?.procurementTerms || null,
|
||||
analysis: preparationAnalysisSource(results),
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
export const tenderStateKey = t => String(t?.ikn || t?.id || '').trim();
|
||||
export const TENDER_SOURCE_FIELDS = [['tarih','İhale tarihi'],['saat','İhale saati'],['durum','İhale durumu'],['baslik','İhale başlığı'],['kurum','İdare'],['alimTuru','Alım türü'],['documentVersion','Doküman sürümü']];
|
||||
export function tenderSourceChanges(previous = {}, current = {}) {
|
||||
return TENDER_SOURCE_FIELDS.flatMap(([field,label]) => {
|
||||
const before = previous[field], after = current[field];
|
||||
if (before == null || before === '' || after == null || after === '' || String(before) === String(after)) return [];
|
||||
return [{field,label,before:String(before),after:String(after)}];
|
||||
});
|
||||
}
|
||||
export const USER_STATE_FIELDS = ['takipte', 'incelendi', 'kanbanStatus', 'atananPersonel', 'gorev', 'notes', 'checklist', 'bidDraft'];
|
||||
export function applyTenderStates(tenders, records = {}) {
|
||||
const seen = new Set();
|
||||
const result = tenders.map(t => {
|
||||
const key = tenderStateKey(t); seen.add(key);
|
||||
const record = records[key];
|
||||
return record ? { ...t, ...record.data } : t;
|
||||
return record ? { ...t, ...record.data, sourceChanges:tenderSourceChanges(record.snapshot,t) } : t;
|
||||
});
|
||||
for (const [key, record] of Object.entries(records)) {
|
||||
if (!seen.has(key) && record.snapshot && (record.data.takipte || record.data.gorev || record.data.incelendi || record.data.bidDraft || record.data.notes?.length))
|
||||
@@ -14,7 +22,7 @@ export function applyTenderStates(tenders, records = {}) {
|
||||
return result;
|
||||
}
|
||||
export function tenderSnapshot(t) {
|
||||
return Object.fromEntries(['id','ikn','baslik','kurum','tarih','saat','sehir','alimTuru'].map(k => [k,t[k] ?? '']));
|
||||
return Object.fromEntries(['id','ikn','baslik','kurum','tarih','saat','sehir','alimTuru','durum','documentVersion'].map(k => [k,t[k] ?? '']));
|
||||
}
|
||||
|
||||
export function publicTender(tender) {
|
||||
|
||||
Reference in New Issue
Block a user