fix: preserve newer tender note drafts after delayed saves

This commit is contained in:
2026-09-06 09:07:23 +03:00
parent d4d9d17a9f
commit 7ad5fb4f50
4 changed files with 59 additions and 19 deletions
+14 -19
View File
@@ -8,12 +8,21 @@ import {
X, Star, Share2, Calendar, MapPin, Building2, Tag, FileText, CheckSquare,
DollarSign, Calculator, Download, Sparkles, AlertTriangle, ShieldCheck,
Send, Stamp, ArrowLeft, ExternalLink, Printer, PenLine } from 'lucide-react';
import { acknowledgeNoteDraft, editNoteDraft } from '../services/noteDrafts';
import { tenderStateKey } from '../services/tenderState';
import { createTenderICS } from '../services/tenderCalendar';
export const TenderDetailModal = () => {
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen, gorevAc, gorevKontrol, aiAnalysisResults, tenders, mutateTender, savingCount, saveError } = useApp();
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen, gorevAc, gorevKontrol, aiAnalysisResults, tenders, mutateTender, savingCount, saveError, authUser } = useApp();
const [activeTab, setActiveTab] = useState('details'); // 'details', 'pdf_stamp', 'ai_assistant', 'checklist', 'kurum_tenders'
const [noteText, setNoteText] = useState('');
const noteOwner = authUser?.email || '';
const [noteDrafts, setNoteDrafts] = useState(() => ({ owner: noteOwner, drafts: {} }));
// Discard private drafts on account changes, before rendering another account.
if (noteDrafts.owner !== noteOwner) setNoteDrafts({ owner: noteOwner, drafts: {} });
const noteKey = tenderStateKey(activeTenderDetail);
const noteDraft = noteDrafts.owner === noteOwner ? noteDrafts.drafts[noteKey] : undefined;
const noteText = noteDraft?.text || '';
const setNoteText = text => setNoteDrafts(state => editNoteDraft(state, noteOwner, noteKey, text));
const [actionError, setActionError] = useState(null);
// Kur Farkı Calculator State
@@ -33,10 +42,6 @@ export const TenderDetailModal = () => {
const usdRate = fx?.rates?.USD;
const eurRate = fx?.rates?.EUR;
// Stamp Drag Position State
const [stampPos, setStampPos] = useState({ x: 220, y: 180 });
const [isDraggingStamp, setIsDraggingStamp] = useState(false);
if (!activeTenderDetail) return null;
// Havuzdaki güncel kayıt: takip/görev değişince düğme etiketleri de değişsin.
const tender = (activeTenderDetail && tenders.find((t) => t.id === activeTenderDetail.id)) || activeTenderDetail;
@@ -51,7 +56,7 @@ export const TenderDetailModal = () => {
text: noteText.trim(),
date: new Date().toLocaleString('tr-TR')
}]});
if (saved) setNoteText('');
if (saved) setNoteDrafts(state => acknowledgeNoteDraft(state, noteOwner, noteKey, noteDraft));
};
const handleExportICS = () => {
@@ -69,17 +74,6 @@ export const TenderDetailModal = () => {
setTimeout(() => URL.revokeObjectURL(link.href), 1000);
};
const handleStampMouseDown = () => setIsDraggingStamp(true);
const handleStampMouseMove = (e) => {
if (!isDraggingStamp) return;
const rect = e.currentTarget.getBoundingClientRect();
setStampPos({
x: Math.max(20, Math.min(rect.width - 150, e.clientX - rect.left - 60)),
y: Math.max(20, Math.min(rect.height - 80, e.clientY - rect.top - 30))
});
};
const handleStampMouseUp = () => setIsDraggingStamp(false);
return (
<div className="fixed inset-0 z-50 overflow-y-auto bg-slate-900/70 backdrop-blur-xs flex justify-center p-2 sm:p-4 animate-fade-in">
<div 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]">
@@ -316,10 +310,11 @@ export const TenderDetailModal = () => {
type="text"
value={noteText}
onChange={(e) => setNoteText(e.target.value)}
aria-label="Ekip notu"
placeholder="Ekip arkadaşlarınıza not yazın..."
className="flex-1 bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-xs"
/>
<button type="submit" className="bg-blue-600 hover:bg-blue-500 text-white font-bold px-4 py-2 rounded-lg text-xs flex items-center gap-1">
<button type="submit" disabled={savingCount > 0 || !noteText.trim()} className="disabled:opacity-50 bg-blue-600 hover:bg-blue-500 text-white font-bold px-4 py-2 rounded-lg text-xs flex items-center gap-1">
<Send className="w-3.5 h-3.5" /> Not Ekle
</button>
</form>
+12
View File
@@ -0,0 +1,12 @@
// Draft objects identify the exact edit submitted; equal text can still be a new edit.
export function editNoteDraft(state, owner, key, text) {
if (state.owner !== owner) return state;
return { ...state, drafts: { ...state.drafts, [key]: { text } } };
}
export function acknowledgeNoteDraft(state, owner, key, submitted) {
if (state.owner !== owner || !submitted || state.drafts[key] !== submitted) return state;
const drafts = { ...state.drafts };
delete drafts[key];
return { ...state, drafts };
}