fix: preserve newer tender note drafts after delayed saves
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
Reference in New Issue
Block a user