From 463fd06d300dc7d50198dd620cd10215948186f6 Mon Sep 17 00:00:00 2001 From: ht Date: Sun, 6 Sep 2026 14:09:31 +0300 Subject: [PATCH] fix: confirm and version favorite institution updates --- docs/quality/uygulama-durumu.md | 6 ++++++ docs/quality/yedek-geri-yukleme.md | 2 ++ server/index.js | 4 +++- src/components/TenderCard.jsx | 4 +++- src/context/AppContext.jsx | 23 +++++++++++++++-------- tests/http-state.test.mjs | 10 ++++++++++ 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index 46298de..07a825a 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -1010,3 +1010,9 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö - İzole QA tarayıcısında altı kontrol geçti: 22 Eylül'deki 10:30 Akdeniz önce, 11:00 Kayseri sonra; Ekim girişinde 31 gün ve 1 Ekim başlığı; sonraki ay Kasım; önceki ay Ekim; bugüne dönüş; Akdeniz detayında aynı tarih/saat. Kanıt qa-calendar-navigation.json. - 228 otomatik test ve derleme geçti. Test sunucusunun çıktısında önceki firma alanı değişikliğinde yinelenmiş aria-invalid niteliği görüldü; tek niteliğe indirildi. Son derleme bu uyarı olmadan geçti; büyük paket uyarısı sürüyor. - QA sekmesi ve yalnız bu test için açılan sunucu kapatıldı (exit 0). Mobil genişlikler, tarihi bilinmeyen kaydın tarayıcı senaryosu ve Google/Outlook aktarımı bu kabul kapsamında değil; açık kalır. Canlıya yayın yapılmadı. + +### Favori kurumlarda kayıt onayı ve sürüm koruması — 6 Eylül 2026 +- Favori kurumların iyimser state/effect kaydı kaldırıldı. Yıldız seçimi ancak sürümlü sunucu yazımı başarılı olunca değişir; hata mevcut listeyi korur ve ortak kayıt hata alanında gösterilir. Bekleme sırasında favori düğmeleri kilitlenir, aria-busy/aria-pressed durumları yayınlanır. +- favori_kurumlar API yazımında okunan içerik sürümü zorunlu; eski sürüm 409 alır. Liste olmayan, boş veya yinelenen kurum girdileri reddedilir. Boş listeye dönmek desteklenir. +- 229 otomatik test ve derleme geçti. HTTP testi sürüm zorunluluğu, art arda başarılı kayıt, eski sekme silme isteğinin reddi, hatalı liste ve son favoriyi kaldırmayı doğruladı. +- Yeni yıldızın tarayıcı bekleme/hata ve iki sekme kabulü açık. Bu değişiklik bildirim aboneliğini otomatik değiştirmez; abonelik kendi kaydedilmiş kurum kapsamını kullanır. Diğer genel anahtarlardan rakip izleme ve hatırlatma ayarlarının eşzamanlı kayıt davranışı ayrıca incelenmeli. Canlıya yayın yapılmadı. diff --git a/docs/quality/yedek-geri-yukleme.md b/docs/quality/yedek-geri-yukleme.md index 206f0da..e088210 100644 --- a/docs/quality/yedek-geri-yukleme.md +++ b/docs/quality/yedek-geri-yukleme.md @@ -77,3 +77,5 @@ Kuyruktaki ilanın artık kaynakta bulunmaması, teklif zamanının değişmesi, `GET /api/me/data` artık `veri` ile aynı okumaya ait `revisions` döndürür. `firma_profil` ve `saved_filters` PUT/POST istekleri `revision` göndermelidir (yeni kayıt için null). Eksik sürüm 428, değişmiş sürüm 409 üretir; otomatik üzerine yazma veya otomatik tekrar yoktur. Frontend ve backend birlikte sürümlenmelidir. Eski açık sekme 428 alırsa kaydedilmemiş girdiler korunup sayfa yenilenmelidir. Veritabanı şeması değişmez; eski sunucuya dönmek bu iki anahtardaki çakışma korumasını kaldırır. Yayın kabulünde iki sekmenin aynı kaydı değiştirmesi ve reddedilen sekmenin girdilerinin korunması sınanmalıdır. Ekip kaydı (`ekip`) da aynı içerik sürümü sözleşmesine dahil edildi. Yeni ekip arayüzü sunucu onayını bekler. Eski istemciden sürümsüz ekip yazımı 428 ile reddedilir; frontend/backend birlikte güncellenmelidir. Ekip alanlarının geçersiz veya kimliklerinin yinelenmiş olduğu eski kayıtlar önce düzeltilmelidir; sessiz veri temizliği yapılmaz. + +Favori kurumlar (`favori_kurumlar`) da sürümlü kullanıcı verisi yazımı ister. Eski istemcinin sürümsüz yazımı 428 döner; frontend/backend birlikte sürümlenmelidir. Bekleyen değişiklikler sunucudan onay gelmeden favori listesinde gösterilmez. diff --git a/server/index.js b/server/index.js index 7ce5f79..9941314 100644 --- a/server/index.js +++ b/server/index.js @@ -1207,7 +1207,9 @@ const server = http.createServer(async (req, res) => { validateTeam(body.deger); kotaKontrol(user.email, 'ekip', 0, body.deger.length, { isAdmin: user.isAdmin }); } - const protectedKey=['firma_profil','saved_filters','ekip'].includes(k); + if(k==='favori_kurumlar' && (!Array.isArray(body.deger) || body.deger.some(name=>typeof name!=='string'||!name.trim()||name.length>1000) || new Set(body.deger.map(name=>name.trim())).size!==body.deger.length)) + return json(res,400,{success:false,error:'Favori kurum listesi geçersiz veya yinelenen kurum içeriyor.'}); + const protectedKey=['firma_profil','saved_filters','ekip','favori_kurumlar'].includes(k); if(protectedKey && (!Object.hasOwn(body,'revision') || (body.revision!==null && (typeof body.revision!=='string' || !/^[a-f0-9]{64}$/.test(body.revision))))) return json(res,428,{success:false,kod:'VERSION_REQUIRED',error:'Güncel kayıt sürümü gerekli. Sayfayı yenileyip tekrar deneyin.'}); const revision=store.setData(user.email, k, body.deger, protectedKey ? body.revision : undefined); diff --git a/src/components/TenderCard.jsx b/src/components/TenderCard.jsx index 4014d61..6148fb8 100644 --- a/src/components/TenderCard.jsx +++ b/src/components/TenderCard.jsx @@ -3,7 +3,7 @@ import { useApp } from '../context/AppContext'; import { Star, MapPin, Clock, Tag, Package, Building2, AlertTriangle, Sparkles, CalendarDays, Megaphone } from 'lucide-react'; export const TenderCard = ({ tender }) => { - const { toggleTrackTender, setActiveTenderDetail, favoriteKurumlar, toggleFavoriteKurum, kalemEslesen, searchQuery } = useApp(); + const { toggleTrackTender, setActiveTenderDetail, favoriteKurumlar, favoriteSaving, toggleFavoriteKurum, kalemEslesen, searchQuery } = useApp(); // Aramada eşleşen kalemler öne alınır — firma kendi ürününü hemen görsün. const eslesenKalemler = (kalemEslesen && tender.ikn && kalemEslesen.get(tender.ikn)) || null; const isFavKurum = favoriteKurumlar?.includes((tender.kurum || '').trim()); @@ -80,6 +80,8 @@ export const TenderCard = ({ tender }) => { {tender.kurum}