import React, { useState, useEffect, useRef } from "react";

// ─── TEMA ────────────────────────────────────────────────────────────────────
const GlobalStyle = ({dark}) => (
  <style>{`
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    button:focus { outline: none; }
    :root { color-scheme: ${dark ? "dark" : "light"}; }
    :root {
      --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    }
    body, input, button, select, textarea {
      font-family: var(--font-sans);
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    input[type="date"]::-webkit-calendar-picker-indicator,
    input[type="month"]::-webkit-calendar-picker-indicator {
      cursor: pointer;
      filter: invert(27%) sepia(90%) saturate(800%) hue-rotate(330deg) brightness(90%);
      opacity: 1;
      width: 15px; height: 15px;
    }
    input[type="date"]::-webkit-calendar-picker-indicator:hover,
    input[type="month"]::-webkit-calendar-picker-indicator:hover {
      filter: invert(15%) sepia(100%) saturate(1200%) hue-rotate(330deg) brightness(80%);
    }
    input[type="date"], input[type="month"] { letter-spacing: normal; }
    :root {
      --th-bg: #1565A0;
      --th-color: #ffffff;
      --tr-even: ${dark ? "#1e2433" : "#f9fafb"};
      --tr-odd:  ${dark ? "#151c2c" : "#ffffff"};
      --tr-hover:${dark ? "#253352" : "#dbeafe33"};
      --grid-line: ${dark ? "rgba(255,255,255,0.07)" : "#d1d5db"};
      --card-bg:  ${dark ? "#151c2c" : "#ffffff"};
      --card-border: ${dark ? "rgba(255,255,255,0.1)" : "#d1d5db"};
      --input-bg: ${dark ? "#1e2433" : "#f3f4f6"};
      --input-border: ${dark ? "rgba(255,255,255,0.15)" : "#d1d5db"};
      --text-primary: ${dark ? "#f1f5f9" : "#111827"};
      --text-secondary: ${dark ? "#94a3b8" : "#374151"};
      --text-tertiary: ${dark ? "#64748b" : "#9ca3af"};
      --sidebar-bg: #1565A0;
      --topbar-bg: #2563A8;
      --page-bg: ${dark ? "#0f1520" : "#f1f5f9"};
      --statusbar-bg: #1565A0;
    }
    body { background: var(--page-bg); font-family: var(--font-sans); }
    .pdks-table thead tr { background: var(--th-bg) !important; }
    .pdks-table thead th { color: var(--th-color) !important; border-right: 1px solid rgba(255,255,255,0.15) !important; padding: 7px 8px; font-size: 11px; font-weight: 600; text-align: left; white-space: nowrap; overflow: hidden; letter-spacing: .02em; font-family: var(--font-sans); }
    .pdks-table tbody tr:nth-child(even) td:not(.shift-cell) { background: var(--tr-even); }
    .pdks-table tbody tr:nth-child(odd) td:not(.shift-cell)  { background: var(--tr-odd); }
    .pdks-table tbody tr:hover td:not(.shift-cell) { background: var(--tr-hover); }
    .shift-cell { background-clip: padding-box; }
    .pdks-table td { border-right: 1px solid var(--grid-line); border-bottom: 1px solid var(--grid-line); padding: 6px 8px; font-size: 12px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-primary); vertical-align: middle; font-family: var(--font-sans); }
    .pdks-table td:last-child, .pdks-table th:last-child { border-right: none; }
    .pdks-card { background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 6px; overflow: hidden; }
    .pdks-input { background: var(--input-bg) !important; border: 1px solid var(--input-border) !important; color: var(--text-primary) !important; }
    .pdks-page { background: var(--page-bg); }
    .pdks-text-primary { color: var(--text-primary); }
    .pdks-text-secondary { color: var(--text-secondary); }
    .pdks-text-tertiary { color: var(--text-tertiary); }
    scrollbar-width: thin;
    ::-webkit-scrollbar { width: 6px; height: 6px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb { background: ${dark?"#334155":"#cbd5e1"}; border-radius: 3px; }
  `}</style>
);

// ─── KULLANICI SİSTEMİ ───────────────────────────────────────────────────────

// Admin'in hangi alanları göstereceğini/gizleyeceğini sakladığı ayarlar
const VARSAYILAN_ALAN_IZINLERI = {
  personel_tc:        { label:"TC Kimlik No",     goster:false, kvkk:true  },
  personel_maas:      { label:"Maaş",              goster:false, kvkk:true  },
  personel_iban:      { label:"IBAN",               goster:false, kvkk:true  },
  personel_dogum:     { label:"Doğum Tarihi",       goster:false, kvkk:true  },
  personel_kan:       { label:"Kan Grubu",          goster:false, kvkk:true  },
  personel_telefon:   { label:"Telefon",            goster:true,  kvkk:false },
  personel_sgk:       { label:"SGK No",             goster:false, kvkk:true  },
  personel_adres:     { label:"Adres",              goster:false, kvkk:true  },
};

const ALAN_IZN_LS_KEY = "pdks_alan_izinleri";

const getAlanIzinleri = () => {
  try {
    const v = localStorage.getItem(ALAN_IZN_LS_KEY);
    if(!v) return VARSAYILAN_ALAN_IZINLERI;
    const saved = JSON.parse(v);
    // Kaydedilen değerleri varsayılanların üzerine yaz (explicit set olanlar)
    const result = {...VARSAYILAN_ALAN_IZINLERI};
    Object.keys(saved).forEach(k => {
      if(result[k]) result[k] = {...result[k], ...saved[k]};
    });
    return result;
  } catch { return VARSAYILAN_ALAN_IZINLERI; }
};

// İzin tipi migration — DS, UI, IS, RI ücretsiz olmalı
try {
  const v = localStorage.getItem("pdks_izinler");
  if(v) {
    const saved = JSON.parse(v);
    const ucretsizKodlar = new Set(["DS","UI","IS","RI"]);
    const guncellendi = saved.map(s => ucretsizKodlar.has(s.kod) ? {...s, tip:"ucretsiz"} : s);
    localStorage.setItem("pdks_izinler", JSON.stringify(guncellendi));
  }
} catch {}
const ALAN_IZN_VERSION = "v3";
try {
  const ver = localStorage.getItem("pdks_alan_izinleri_ver");
  if(ver !== ALAN_IZN_VERSION) {
    localStorage.removeItem("pdks_alan_izinleri");
    localStorage.setItem("pdks_alan_izinleri_ver", ALAN_IZN_VERSION);
  }
} catch {}

const saveAlanIzinleri = (obj) => {
  try {
    const overrides = {};
    Object.keys(obj).forEach(k => {
      overrides[k] = {goster: obj[k].goster};
    });
    localStorage.setItem(ALAN_IZN_LS_KEY, JSON.stringify(overrides));
  } catch {}
};

// Varsayılan kullanıcılar
const VARSAYILAN_KULLANICILAR = [
  { id:"admin",  ad:"Admin",  soyad:"Yönetici",  sifre:"admin123",  yetki:"admin",    departmanlar:[], aktif:true },
  { id:"pinar",  ad:"Pınar",  soyad:"Taşseven",  sifre:"pinar123",  yetki:"kullanici",departmanlar:["İNSAN KAYNAKLARI"], aktif:true },
  { id:"mehmet", ad:"Mehmet", soyad:"Baş",        sifre:"mehmet123", yetki:"kullanici",departmanlar:["BAHÇE İŞLERİ"], aktif:true },
];

const KUL_LS_KEY = "pdks_kullanicilar";

const getKullanicilar = () => {
  try { const v=localStorage.getItem(KUL_LS_KEY); return v?JSON.parse(v):VARSAYILAN_KULLANICILAR; }
  catch { return VARSAYILAN_KULLANICILAR; }
};
const saveKullanicilar = (list) => {
  try { localStorage.setItem(KUL_LS_KEY, JSON.stringify(list)); } catch {}
};
if(!localStorage.getItem(KUL_LS_KEY)) saveKullanicilar(VARSAYILAN_KULLANICILAR);

// Yetki etiketleri ve renkleri
// yetki: "admin" | "kullanici"  (izleme kaldırıldı — kullanıcı = kısıtlı erişim)
const yetkiLabel = {admin:"Admin", kullanici:"Kullanıcı"};
const yetkiRenk  = {
  admin:    {bg:"#EEEDFE", c:"#534AB7"},
  kullanici:{bg:"#EAF3DE", c:"#3B6D11"},
};

// ─── YETKİ KONTROL FONKSİYONLARI ─────────────────────────────────────────────

// Departman görme yetkisi
// Admin → hepsi | Kullanıcı → sadece atanan departmanlar
const gorebilirMi = (kul, dept) => {
  if(!kul) return false;
  if(kul.yetki==="admin") return true;
  return (kul.departmanlar||[]).includes(dept);
};

// Modül erişim yetkisi
// Admin → hepsi | Kullanıcı → sadece izin verilen modüller
// Firma parametreleri migration — eski false değerlerini düzelt
try {
  const v = localStorage.getItem("pdks_firma_parametreleri");
  if(v) {
    const saved = JSON.parse(v);
    // departmanPuantajYetkisi ve departmanIzinGirisYetkisi false ise
    // ve kullanıcı açıkça kapatmamışsa true'ya çevir
    if(saved.departmanPuantajYetkisi === false && !saved._puantajYetkisiAcikca) {
      saved.departmanPuantajYetkisi = true;
      localStorage.setItem("pdks_firma_parametreleri", JSON.stringify(saved));
    }
    if(saved.departmanIzinGirisYetkisi === false && !saved._izinYetkisiAcikca) {
      saved.departmanIzinGirisYetkisi = true;
      localStorage.setItem("pdks_firma_parametreleri", JSON.stringify(saved));
    }
  }
} catch {}

// Firma parametrelerini her yerden oku
const getFirmaParams = () => {
  try { const v=localStorage.getItem("pdks_firma_parametreleri"); return v?JSON.parse(v):{} } catch { return {}; }
};

const modulGorebilirMi = (kul, modul) => {
  if(!kul) return false;
  if(kul.yetki==="admin") return true;
  // Kullanıcının her zaman görebileceği modüller
  const izinliModuller = ["hatali","puantaj","shift","personel"];
  return izinliModuller.includes(modul);
};

// Düzenleme yetkisi — sadece shift atama
const duzenleyebilirMi = (kul, ekran) => {
  if(!kul) return false;
  if(kul.yetki==="admin") return true;
  // Kullanıcı sadece shift atama ekranında değişiklik yapabilir
  return ekran==="shift";
};

// Alan görme yetkisi (KVKK alanları) — izinler parametresi React state'ten gelir
const alanGorebilirMi = (kul, alanKey, izinler) => {
  if(!kul) return false;
  if(kul.yetki==="admin") return true; // admin her zaman görür
  const guncelIzinler = izinler || getAlanIzinleri();
  return guncelIzinler[alanKey]?.goster !== false;
};

// localStorage yardımcıları — kullanıcıya özel key
const lsGet = (uid, key, def) => {
  try { const v = localStorage.getItem(`pdks_${uid}_${key}`); return v ? JSON.parse(v) : def; }
  catch { return def; }
};
const lsSet = (uid, key, val) => {
  try { localStorage.setItem(`pdks_${uid}_${key}`, JSON.stringify(val)); } catch {}
};

// Sütun state'ini localStorage'a bağlayan hook
const usePersistentCols = (uid, key, defaults) => {
  const [cols, setColsRaw] = useState(() => lsGet(uid, key+"_cols", defaults));
  const [hidden, setHiddenRaw] = useState(() => new Set(lsGet(uid, key+"_hidden", [])));

  const setCols = (v) => { setColsRaw(v); lsSet(uid, key+"_cols", v); };
  const setHidden = (fn) => {
    setHiddenRaw(prev => {
      const next = typeof fn === "function" ? fn(prev) : fn;
      lsSet(uid, key+"_hidden", [...next]);
      return next;
    });
  };
  return [cols, setCols, hidden, setHidden];
};

// ─── GİRİŞ EKRANI ────────────────────────────────────────────────────────────
const LoginEkrani = ({onLogin}) => {
  const [kullanici, setKullanici] = useState("");
  const [sifre, setSifre] = useState("");
  const [hata, setHata] = useState("");
  const [sifregizle, setSifreGizle] = useState(true);
  const [loading, setLoading] = useState(false);

  const girisYap = () => {
    const liste = getKullanicilar(); const k = liste.find(u => u.id===kullanici && u.sifre===sifre && u.aktif!==false);
    if(k) {
      setLoading(true);
      // Kısa gecikme — state güncellemesinin render'a fırsat vermesi için
      requestAnimationFrame(() => requestAnimationFrame(() => onLogin(k)));
    } else {
      setHata("Kullanıcı adı veya şifre hatalı");
    }
  };

  const iStyle = {
    width:"100%", padding:"12px 14px 12px 42px",
    border:"1.5px solid rgba(255,255,255,0.1)",
    borderRadius:10, background:"#1a2234",
    color:"#f1f5f9", fontSize:14, fontFamily:"var(--font-sans)",
    outline:"none", boxSizing:"border-box",
  };

  return (
    <div style={{display:"flex",height:"100vh",fontFamily:"var(--font-sans)"}}>

      {/* Sol panel */}
      <div style={{flex:1,background:"#0c2340",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:48,position:"relative",overflow:"hidden"}}>
        <div style={{position:"absolute",width:400,height:400,borderRadius:"50%",border:"1px solid rgba(255,255,255,0.05)",top:-80,right:-80}} />
        <div style={{position:"absolute",width:300,height:300,borderRadius:"50%",border:"1px solid rgba(255,255,255,0.04)",bottom:-60,left:-60}} />
        <div style={{position:"relative",zIndex:1,textAlign:"center",maxWidth:320}}>
          <div style={{width:68,height:68,background:"#1565A0",borderRadius:18,display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto 20px"}}>
            <svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
              <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/>
              <path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>
            </svg>
          </div>
          <div style={{fontSize:30,fontWeight:700,color:"#fff",marginBottom:8}}>TimeCore</div>
          <div style={{fontSize:14,color:"rgba(255,255,255,0.55)",marginBottom:36}}>Personel Devam Kontrol Sistemi</div>
          {[["📊","Anlık devam takibi"],["📅","Shift planlama"],["📋","Aylık puantaj"],["👤","Çok kullanıcı"]].map(([ic,tx])=>(
            <div key={tx} style={{display:"flex",alignItems:"center",gap:12,marginBottom:12,textAlign:"left"}}>
              <div style={{width:34,height:34,borderRadius:9,background:"rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:15,flexShrink:0}}>{ic}</div>
              <span style={{color:"rgba(255,255,255,0.7)",fontSize:13}}>{tx}</span>
            </div>
          ))}
        </div>
        <div style={{position:"absolute",bottom:20,color:"rgba(255,255,255,0.2)",fontSize:11}}>v1.0 · {new Date().getFullYear()}</div>
      </div>

      {/* Sağ panel */}
      <div style={{width:420,background:"#0f1520",display:"flex",alignItems:"center",justifyContent:"center",padding:"0 48px"}}>
        <div style={{width:"100%"}}>
          <div style={{marginBottom:28}}>
            <div style={{fontSize:22,fontWeight:700,color:"#f1f5f9",marginBottom:6}}>Hoş geldiniz</div>
            <div style={{fontSize:13,color:"#64748b"}}>Devam etmek için giriş yapın</div>
          </div>

          {/* Kullanıcı adı */}
          <div style={{marginBottom:14}}>
            <label style={{display:"block",fontSize:11,fontWeight:600,color:"#64748b",marginBottom:7,letterSpacing:.06}}>KULLANICI ADI</label>
            <div style={{position:"relative"}}>
              <svg style={{position:"absolute",left:13,top:"50%",transform:"translateY(-50%)",pointerEvents:"none"}} width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#475569" strokeWidth="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
              <input value={kullanici} onChange={e=>{setKullanici(e.target.value);setHata("");}}
                placeholder="kullanici_adi" onKeyDown={e=>e.key==="Enter"&&girisYap()}
                style={iStyle} />
            </div>
          </div>

          {/* Şifre */}
          <div style={{marginBottom:20}}>
            <label style={{display:"block",fontSize:11,fontWeight:600,color:"#64748b",marginBottom:7,letterSpacing:.06}}>ŞİFRE</label>
            <div style={{position:"relative"}}>
              <svg style={{position:"absolute",left:13,top:"50%",transform:"translateY(-50%)",pointerEvents:"none"}} width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#475569" strokeWidth="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
              <input type={sifregizle?"password":"text"} value={sifre}
                onChange={e=>{setSifre(e.target.value);setHata("");}}
                placeholder="••••••••" onKeyDown={e=>e.key==="Enter"&&girisYap()}
                style={{...iStyle,paddingRight:42}} />
              <button onClick={()=>setSifreGizle(g=>!g)} style={{position:"absolute",right:12,top:"50%",transform:"translateY(-50%)",background:"none",border:"none",color:"#475569",cursor:"pointer",padding:2,display:"flex"}}>
                {sifregizle
                  ? <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
                  : <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
                }
              </button>
            </div>
          </div>

          {/* Hata */}
          {hata && (
            <div style={{display:"flex",alignItems:"center",gap:8,background:"rgba(163,45,45,0.15)",border:"1px solid rgba(163,45,45,0.3)",color:"#f87171",padding:"9px 12px",borderRadius:8,fontSize:12,marginBottom:14}}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
              {hata}
            </div>
          )}

          {/* Giriş */}
          <button onClick={girisYap} disabled={loading}
            style={{width:"100%",padding:"12px",background:"#1565A0",border:"none",borderRadius:10,color:"#fff",fontSize:14,fontWeight:600,cursor:loading?"default":"pointer",fontFamily:"var(--font-sans)",display:"flex",alignItems:"center",justifyContent:"center",gap:8}}>
            {loading
              ? "Giriş yapılıyor..."
              : <><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg> Giriş Yap</>
            }
          </button>

          {/* Test kullanıcıları */}
          <div style={{marginTop:20,padding:12,background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)",borderRadius:8}}>
            <div style={{fontSize:10,color:"#475569",marginBottom:7,fontWeight:600,letterSpacing:.06}}>TEST KULLANICILARI — tıklayarak doldur</div>
            {getKullanicilar().map(k=>(
              <div key={k.id} onClick={()=>{setKullanici(k.id);setSifre(k.sifre);setHata("");}}
                style={{display:"flex",alignItems:"center",gap:8,padding:"5px 6px",cursor:"pointer",borderRadius:6,marginBottom:2}}
                onMouseEnter={e=>e.currentTarget.style.background="rgba(255,255,255,0.05)"}
                onMouseLeave={e=>e.currentTarget.style.background=""}>
                <span style={{color:"#60a5fa",fontFamily:"monospace",fontSize:12,minWidth:60}}>{k.id}</span>
                <span style={{color:"#475569",fontSize:12,flex:1}}>{k.ad} {k.soyad}</span>
                <span style={{color:"#334155",fontSize:10,background:"rgba(255,255,255,0.06)",padding:"1px 7px",borderRadius:4}}>{yetkiLabel[k.yetki]||k.yetki}</span>
              </div>
            ))}
          </div>

          {/* Alan izinleri sıfırlama */}
          <div style={{marginTop:12,textAlign:"center"}}>
            <button onClick={()=>{
              localStorage.removeItem("pdks_alan_izinleri");
              localStorage.removeItem("pdks_alan_izinleri_ver");
              alert("✓ Alan izinleri sıfırlandı. Şimdi Admin ile giriş yapıp Tanımlar → Kullanıcılar → Alan İzinleri'nden ayarlayın.");
            }} style={{background:"none",border:"none",color:"#475569",fontSize:11,cursor:"pointer",textDecoration:"underline",fontFamily:"var(--font-sans)"}}>
              Alan izinlerini sıfırla
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};



const VARSAYILAN_SHIFTS = [
  { kod:"A",  ad:"A Vardiyası", giris:"08:00", cikis:"16:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"12:00", antraktCikis:"13:00", tanımliMesai:0, siraNo:1, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#3B6D11", bg:"#EAF3DE" },
  { kod:"B",  ad:"B Vardiyası", giris:"16:00", cikis:"00:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"20:00", antraktCikis:"21:00", tanımliMesai:0, siraNo:2, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#185FA5", bg:"#E6F1FB" },
  { kod:"C",  ad:"C Vardiyası", giris:"23:59", cikis:"08:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"03:00", antraktCikis:"03:30", tanımliMesai:0, siraNo:3, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#534AB7", bg:"#EEEDFE" },
  { kod:"D",  ad:"D Vardiyası", giris:"12:30", cikis:"21:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"16:00", antraktCikis:"17:00", tanımliMesai:0, siraNo:4, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#854F0B", bg:"#FAEEDA" },
  { kod:"G",  ad:"G Vardiyası", giris:"08:30", cikis:"17:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"12:30", antraktCikis:"13:30", tanımliMesai:0, siraNo:5, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#0F6E56", bg:"#E1F5EE" },
  { kod:"F",  ad:"F Vardiyası", giris:"07:00", cikis:"15:00", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"11:00", antraktCikis:"12:00", tanımliMesai:0, siraNo:6, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#993C1D", bg:"#FAECE7" },
  { kod:"H",  ad:"H Vardiyası", giris:"08:00", cikis:"21:30", muafiyet:30, cikisMuafiyet:30, servisGiris:45, servisCikis:30, antraktGiris:"12:30", antraktCikis:"16:30", tanımliMesai:0, siraNo:7, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#5F5E5A", bg:"#F1EFE8" },
  { kod:"OFF",ad:"Off",          giris:"",     cikis:"",     muafiyet:0,  cikisMuafiyet:0,  servisGiris:0,  servisCikis:0,  antraktGiris:"",     antraktCikis:"",     tanımliMesai:0, siraNo:8, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#5F5E5A", bg:"#F1EFE8" },
  { kod:"RT", ad:"Resmi Tatil",  giris:"",     cikis:"",     muafiyet:0,  cikisMuafiyet:0,  servisGiris:0,  servisCikis:0,  antraktGiris:"",     antraktCikis:"",     tanımliMesai:0, siraNo:9, yarimGun:false, kullanimda:true, araDinlenmeler:[], renk:"#A32D2D", bg:"#FCEBEB" },
];

// İzin kodları — ayrı store, Shift Atama ekranında da kullanılır
const VARSAYILAN_IZINLER = [
  { kod:"YI", ad:"Yıllık İzin",           renk:"#185FA5", bg:"#E6F1FB", tip:"ucretli" },
  { kod:"HI", ad:"Haftalık İzin",         renk:"#0F6E56", bg:"#E1F5EE", tip:"ucretli" },
  { kod:"RT", ad:"Resmi Tatil",           renk:"#534AB7", bg:"#EEEDFE", tip:"ucretli" },
  { kod:"GV", ad:"Görevli",               renk:"#534AB7", bg:"#EEEDFE", tip:"ucretli" },
  { kod:"DI", ad:"Doğum İzni",            renk:"#D4537E", bg:"#FBEAF0", tip:"ucretli" },
  { kod:"EI", ad:"Evlilik İzni",          renk:"#185FA5", bg:"#E6F1FB", tip:"ucretli" },
  { kod:"OI", ad:"Ölüm İzni",             renk:"#5F5E5A", bg:"#F1EFE8", tip:"ucretli" },
  { kod:"II", ad:"İdari İzin",            renk:"#0F6E56", bg:"#E1F5EE", tip:"ucretli" },
  { kod:"SZ", ad:"Serbest Zaman",         renk:"#534AB7", bg:"#EEEDFE", tip:"ucretli" },
  { kod:"DK", ad:"Denkleştirme",          renk:"#3B6D11", bg:"#EAF3DE", tip:"ucretli" },
  { kod:"TL", ad:"Telafi",                renk:"#0F6E56", bg:"#E1F5EE", tip:"ucretli" },
  { kod:"IH", ad:"İhbar İzni",            renk:"#A32D2D", bg:"#FCEBEB", tip:"ucretli" },
  { kod:"VZ", ad:"Viziteli",              renk:"#854F0B", bg:"#FAEEDA", tip:"ucretli" },
  { kod:"KO", ad:"Kısa Çalışma Ödeneği", renk:"#185FA5", bg:"#E6F1FB", tip:"ucretli" },
  { kod:"DS", ad:"Devamsız",              renk:"#A32D2D", bg:"#FCEBEB", tip:"ucretsiz" },
  { kod:"UI", ad:"Ücretsiz İzin",         renk:"#854F0B", bg:"#FAEEDA", tip:"ucretsiz" },
  { kod:"IS", ad:"İstirahat (Rapor)",     renk:"#993C1D", bg:"#FAECE7", tip:"ucretsiz" },
  { kod:"RI", ad:"Raporlu",              renk:"#993C1D", bg:"#FAECE7", tip:"ucretsiz" },
];

const IZINLER_LS_KEY = "pdks_izinler";
const getIzinler = () => {
  try { const v=localStorage.getItem(IZINLER_LS_KEY); return v?JSON.parse(v):VARSAYILAN_IZINLER; }
  catch { return VARSAYILAN_IZINLER; }
};
const saveIzinler = (list) => {
  try { localStorage.setItem(IZINLER_LS_KEY, JSON.stringify(list)); } catch {}
};
if(!localStorage.getItem(IZINLER_LS_KEY)) {
  saveIzinler(VARSAYILAN_IZINLER);
} else {
  // Yeni eklenen izin tiplerini mevcut listeye merge et
  const mevcut = getIzinler();
  const mevcutKodlar = new Set(mevcut.map(i=>i.kod));
  const yeniEklenenler = VARSAYILAN_IZINLER.filter(i=>!mevcutKodlar.has(i.kod));
  if(yeniEklenenler.length > 0) {
    saveIzinler([...yeniEklenenler, ...mevcut]);
  }
}
let IZINLER = getIzinler();

const SHIFTS_LS_KEY = "pdks_shifts";
const getShifts = () => {
  try { const v=localStorage.getItem(SHIFTS_LS_KEY); return v?JSON.parse(v):VARSAYILAN_SHIFTS; }
  catch { return VARSAYILAN_SHIFTS; }
};
const saveShifts = (list) => {
  try { localStorage.setItem(SHIFTS_LS_KEY, JSON.stringify(list)); } catch {}
};
// SHIFTS versiyonlama — siraNo olmayan eski kayıtları sıfırla
try {
  if(localStorage.getItem(SHIFTS_LS_KEY + "_ver") !== "v3") {
    localStorage.removeItem(SHIFTS_LS_KEY);
    localStorage.setItem(SHIFTS_LS_KEY + "_ver", "v3");
  }
} catch {}
if(!localStorage.getItem(SHIFTS_LS_KEY)) saveShifts(VARSAYILAN_SHIFTS);

// Runtime cache — component'ler buradan okur, Tanimlar'da değişince güncellenir
const siralanmisShifts = (list) => [...list].sort((a,b) => (a.siraNo||99) - (b.siraNo||99));
let SHIFTS = siralanmisShifts(getShifts());

const DEPARTMANLAR = ["ANİMASYON","BAR","BAHÇE İŞLERİ","ÇAMAŞIRHANE","GÜVENLİK","HOUSEKEEPING","İNSAN KAYNAKLARI","MALİ İŞLER","MUTFAK","ÖN BÜRO","SERVİS","STEWARD","TEKNİK SERVİS"];
const DEPT_LS_KEY = "pdks_departmanlar";
const getDepartmanlar = () => {
  try {
    const v = localStorage.getItem(DEPT_LS_KEY);
    if(v) {
      const saved = JSON.parse(v);
      // Eski format: string array → nesneye çevir
      if(saved.length && typeof saved[0] === "string")
        return saved.map(d => ({ad:d, aciklama:""}));
      return saved;
    }
  } catch {}
  return DEPARTMANLAR.map(d => ({ad:d, aciklama:""}));
};
const saveDepartmanlar = (list) => {
  try { localStorage.setItem(DEPT_LS_KEY, JSON.stringify(list)); } catch {}
};
if(!localStorage.getItem(DEPT_LS_KEY)) saveDepartmanlar(DEPARTMANLAR.map(d=>({ad:d, aciklama:""})));

// Görevler — departmana bağlı, sıra numaralı
// Görev kademeleri — sabit liste
const KADEME_LISTESI = ["Müdür","Müdür Yardımcısı","Şef","Sorumlu","Eleman","Stajyer"];

// Format: [{departman, ad, aciklama, kademe, siraNo}]
const GOREVLER_LS_KEY = "pdks_gorevler";
const VARSAYILAN_GOREVLER = [
  {departman:"ANİMASYON",    ad:"Animasyon Şefi",     aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"ANİMASYON",    ad:"Animatör",            aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"ANİMASYON",    ad:"Mini Club Elemanı",   aciklama:"", kademe:"Eleman",  siraNo:3},
  {departman:"ANİMASYON",    ad:"DJ",                  aciklama:"", kademe:"Eleman",  siraNo:4},
  {departman:"ANİMASYON",    ad:"Ses Işık Şefi",       aciklama:"", kademe:"Şef",     siraNo:5},
  {departman:"BAR",          ad:"Bar Şef",             aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"BAR",          ad:"Barman / Barmaid",    aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"BAR",          ad:"Bar Garson",          aciklama:"", kademe:"Eleman",  siraNo:3},
  {departman:"BAHÇE İŞLERİ", ad:"Bahçe Şefi",         aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"BAHÇE İŞLERİ", ad:"Bahçıvan",           aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"ÇAMAŞIRHANE",  ad:"Çamaşırhane Elemanı",aciklama:"", kademe:"Eleman",  siraNo:1},
  {departman:"GÜVENLİK",     ad:"Güvenlik Personeli", aciklama:"", kademe:"Eleman",  siraNo:1},
  {departman:"HOUSEKEEPING", ad:"Kat Şefi",           aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"HOUSEKEEPING", ad:"Kat Görevlisi",      aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"İNSAN KAYNAKLARI", ad:"İnsan Kaynakları Müdürü", aciklama:"", kademe:"Müdür",  siraNo:1},
  {departman:"İNSAN KAYNAKLARI", ad:"İnsan Kaynakları Memuru", aciklama:"", kademe:"Eleman", siraNo:2},
  {departman:"MALİ İŞLER",   ad:"Mali İşler Müdürü",  aciklama:"", kademe:"Müdür",   siraNo:1},
  {departman:"MUTFAK",       ad:"Souse Şefi",          aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"MUTFAK",       ad:"Demi Şef 1",          aciklama:"", kademe:"Şef",     siraNo:2},
  {departman:"MUTFAK",       ad:"Komı",                aciklama:"", kademe:"Eleman",  siraNo:3},
  {departman:"ÖN BÜRO",      ad:"Resepsiyon Şefi",    aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"ÖN BÜRO",      ad:"Resepsiyonist",      aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"SERVİS",       ad:"Garson",              aciklama:"", kademe:"Eleman",  siraNo:1},
  {departman:"SERVİS",       ad:"Garson-2",            aciklama:"", kademe:"Eleman",  siraNo:2},
  {departman:"STEWARD",      ad:"Steward Şefi",        aciklama:"", kademe:"Şef",     siraNo:1},
  {departman:"TEKNİK SERVİS",ad:"Teknik Eleman",       aciklama:"", kademe:"Eleman",  siraNo:1},
  {departman:"TEKNİK SERVİS",ad:"Elektrikçi",          aciklama:"", kademe:"Eleman",  siraNo:2},
];
const getGorevler = () => {
  try {
    const v = localStorage.getItem(GOREVLER_LS_KEY);
    if(v) return JSON.parse(v);
  } catch {}
  return VARSAYILAN_GOREVLER;
};
const saveGorevler = (list) => {
  try { localStorage.setItem(GOREVLER_LS_KEY, JSON.stringify(list)); } catch {}
};
if(!localStorage.getItem(GOREVLER_LS_KEY)) saveGorevler(VARSAYILAN_GOREVLER);

// Geriye uyumluluk — personel kartı gibi yerler için düz liste
const GOREVLER = getGorevler().map(g=>g.ad);
const getGorevlerForDept = (dept) =>
  getGorevler().filter(g=>g.departman===dept).sort((a,b)=>(a.siraNo||99)-(b.siraNo||99));

const initPersonel = [
  { id:1, sicil:"M.187.1188", tc:"30337488600", ad:"ATAKAN", soyad:"DUGAN", departman:"ANİMASYON", gorev:"Animasyon Şefi", calismaGrubu:"NOR. ÇL.", isGiris:"01.05.2025", istenCikis:"", durum:"Çalışıyor", telefon:"0532 111 22 33", dogumTarihi:"19.07.1992", kanGrubu:"A+", maas:45000, cihazNo:"207", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"01.05.2025", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:2, sicil:"M.187.1189", tc:"16453653000", ad:"FERHAT", soyad:"PORTAKAL", departman:"ANİMASYON", gorev:"Animatör", calismaGrubu:"NOR. ÇL.", isGiris:"01.05.2025", istenCikis:"", durum:"Çalışıyor", telefon:"0533 222 33 44", dogumTarihi:"26.05.1995", kanGrubu:"B+", maas:32000, cihazNo:"", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"01.05.2025", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:3, sicil:"M.187.1208", tc:"99858998200", ad:"ALEKSAND", soyad:"KİRİLLOVA", departman:"ANİMASYON", gorev:"Animatör", calismaGrubu:"NOR. ÇL.", isGiris:"20.05.2026", istenCikis:"", durum:"Çalışıyor", telefon:"", dogumTarihi:"22.01.2001", kanGrubu:"", maas:28000, cihazNo:"419", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"20.05.2026", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:4, sicil:"L.170.1029", tc:"18580426500", ad:"İBRAHİM", soyad:"DENİZ", departman:"BAHÇE İŞLERİ", gorev:"Bahçe Şefi", calismaGrubu:"NOR. ÇL.", isGiris:"01.09.2023", istenCikis:"", durum:"Çalışıyor", telefon:"0534 333 44 55", dogumTarihi:"10.07.1956", kanGrubu:"0+", maas:38000, cihazNo:"133", dolapNo:"5", lojmanNo:"12", sgkNo:"", sskTar:"", sirketGiris:"01.09.2023", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"İlkokul", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:5, sicil:"L.171.1568", tc:"20725738800", ad:"MEHMET", soyad:"BAŞ", departman:"BAHÇE İŞLERİ", gorev:"Bahçıvan", calismaGrubu:"NOR. ÇL.", isGiris:"24.03.2026", istenCikis:"", durum:"Çalışıyor", telefon:"", dogumTarihi:"28.08.1961", kanGrubu:"", maas:26000, cihazNo:"77", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"24.03.2026", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:6, sicil:"M.187.1244", tc:"10760334000", ad:"ŞEYMA", soyad:"GÜNYELİ", departman:"ANİMASYON", gorev:"Mini Club Elemanı", calismaGrubu:"NOR. ÇL.", isGiris:"09.04.2026", istenCikis:"", durum:"Çalışıyor", telefon:"0537 555 66 77", dogumTarihi:"07.06.2004", kanGrubu:"A+", maas:27000, cihazNo:"219", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"09.04.2026", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"Üniversite", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
  { id:7, sicil:"M.187.1173", tc:"57748592400", ad:"ORKAN", soyad:"UÇAR", departman:"ANİMASYON", gorev:"Ses Işık Şefi", calismaGrubu:"NOR. ÇL.", isGiris:"11.04.2025", istenCikis:"", durum:"Çalışıyor", telefon:"0538 666 77 88", dogumTarihi:"24.04.1991", kanGrubu:"B-", maas:42000, cihazNo:"15", dolapNo:"3", lojmanNo:"", sgkNo:"", sskTar:"", sirketGiris:"11.04.2025", devamKontrol:"Yapılacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"Lise", acilGrup:"", uiDevir:0, yiDevir:3, notlar:"" },
  { id:8, sicil:"P.001.0001", tc:"23932384352", ad:"PINAR", soyad:"TAŞSEVEN", departman:"İNSAN KAYNAKLARI", gorev:"İnsan Kaynakları Müdürü", calismaGrubu:"NOR. ÇL.", isGiris:"13.05.2026", istenCikis:"", durum:"Çalışıyor", telefon:"5437159486", dogumTarihi:"31.07.1986", kanGrubu:"A+", maas:75000, cihazNo:"0", dolapNo:"", lojmanNo:"", sgkNo:"", sskTar:"13.05.2026", sirketGiris:"13.05.2026", devamKontrol:"Yapılmayacak", servis:"", durak:"", hesDoku:"", bordroSicil:"", ogrenim:"Üniversite", acilGrup:"", uiDevir:0, yiDevir:0, notlar:"" },
];

// ─── HAREKET VERİSİ & HATA MANTIĞI ──────────────────────────────────────────

// Saat string'ini dakikaya çevir: "08:30" → 510
const saatDk = (s) => {
  if(!s) return null;
  const [h,m] = s.split(":").map(Number);
  return h*60+m;
};
const dkSaat = (dk) => `${String(Math.floor(((dk||0)%1440+1440)%1440/60)).padStart(2,"0")}:${String(((dk||0)%1440+1440)%1440%60).padStart(2,"0")}`;

// Shift kodundan başlangıç/bitiş dakikası çıkar
const shiftSaatleri = (shiftKod) => {
  const s = SHIFTS.find(x=>x.kod===shiftKod);
  if(!s) return null;
  const giris = s.giris || (s.saat ? s.saat.split("-")[0] : null);
  const cikis = s.cikis || (s.saat ? s.saat.split("-")[1] : null);
  if(!giris || !cikis) return null;

  let baslangic = saatDk(giris);
  let bitis = saatDk(cikis);
  if(bitis === 0) bitis = 1440;
  if(bitis < baslangic) bitis += 1440;

  // Antract aralığı — bu saatler arasında çıkış olması normaldir
  const antraktBas = s.antraktGiris ? saatDk(s.antraktGiris) : null;
  const antraktBit = s.antraktCikis ? saatDk(s.antraktCikis) : null;

  // Ara dinlenmeler (birden fazla antract desteği)
  const araDinlenmeler = (s.araDinlenmeler||[]).map(d => ({
    bas: saatDk(d.baslangic),
    bit: saatDk(d.bitis),
  })).filter(d => d.bas!==null && d.bit!==null);

  return {
    baslangic, bitis,
    antraktBas, antraktBit,
    araDinlenmeler,
    girisToler: s.muafiyet || 30,
    cikisToler: s.cikisMuafiyet || 30,
  };
};

const hataDetect = (shiftKod, gGiris, gCikis, tarih, bugunTarih, toleransDk=30) => {
  const hatalar = [];

  // İzin günlerinde giriş/çıkış varsa hata — taze oku
  const izinlerGuncel = getIzinler();
  const izinMi = izinlerGuncel.some(i=>i.kod===shiftKod);
  if(izinMi) {
    if(gGiris || gCikis) {
      hatalar.push({tip:"İZİNDE ÇALIŞTI", aciklama:`${shiftKod} izni var ancak giriş/çıkış kaydı mevcut`});
    }
    return hatalar;
  }

  const ss = shiftSaatleri(shiftKod);
  // OFF günü veya shift tanımı yoksa — giriş/çıkış beklenmez, hata yok
  if(!ss) return hatalar;

  const girisToler = ss.girisToler || toleransDk;
  const cikisToler = ss.cikisToler || toleransDk;
  const girisDk = saatDk(gGiris);
  const now = new Date();
  const bugun = tarih === bugunTarih;

  // Gece yarısını geçen vardiyada çıkış saati düzeltmesi
  let cikisDk = saatDk(gCikis);
  if(cikisDk !== null && ss.bitis >= 1440 && cikisDk < ss.baslangic) {
    cikisDk += 1440;
  }

  // Çıkışın antract saatine denk gelip gelmediğini kontrol et
  // Antract veya ara dinlenme sırasında çıkış → ÇIKIŞ YOK hata sayılmaz, ERKEN/GEÇ sayılmaz
  const antraktCikismi = (dk) => {
    if(dk === null) return false;
    // Ana antract
    if(ss.antraktBas!==null && ss.antraktBit!==null) {
      if(dk >= ss.antraktBas - 10 && dk <= ss.antraktBit + 10) return true;
    }
    // Ara dinlenmeler
    for(const d of (ss.araDinlenmeler||[])) {
      if(dk >= d.bas - 10 && dk <= d.bit + 10) return true;
    }
    return false;
  };

  // Gece yarısını geçen vardiyada GİRİŞ saati düzeltmesi
  // Örn: 23:59 başlangıçlı vardiyada 00:00-00:30 girişi → 1440+0=1440 dk olarak değerlendir
  let girisDkDuz = girisDk;
  if(girisDk !== null && ss.baslangic > 1200 && girisDk < 400) {
    // Gece yarısını geçmiş — 1440 ekle
    girisDkDuz = girisDk + 1440;
  }

  if(!gGiris) {
    hatalar.push({tip:"GİRİŞ YOK", aciklama:"Cihazda giriş kaydı bulunamadı"});
    if(!gCikis) {
      const simdiDk = now.getHours()*60+now.getMinutes();
      const gecti = !bugun || simdiDk > ss.bitis + cikisToler;
      if(gecti) {
        hatalar.push({tip:"ÇIKIŞ YOK", aciklama:`Vardiya bitiş ${dkSaat(ss.bitis%1440)} geçti, çıkış kaydı yok`});
      }
    }
    return hatalar;
  }

  // Giriş kontrolü:
  // Muafiyet SADECE erken girişe uygulanır: (baslangic - girisToler) ile baslangic arası normal
  // Geç giriş: baslangic'ten sonra her zaman hata (muafiyet yok)
  if(girisDkDuz < ss.baslangic - girisToler) {
    hatalar.push({tip:"ERKEN GİRİŞ", aciklama:`Vardiya ${dkSaat(ss.baslangic%1440)} — Giriş ${gGiris} (${ss.baslangic-girisDkDuz} dk erken)`});
  }
  if(girisDkDuz > ss.baslangic) {
    hatalar.push({tip:"GEÇ GİRİŞ", aciklama:`Vardiya ${dkSaat(ss.baslangic%1440)} — Giriş ${gGiris} (${girisDkDuz-ss.baslangic} dk geç)`});
  }

  if(!gCikis) {
    const simdiDk = now.getHours()*60+now.getMinutes();
    const gecti = !bugun || simdiDk > ss.bitis + cikisToler;
    if(gecti) {
      hatalar.push({tip:"ÇIKIŞ YOK", aciklama:`Vardiya bitiş ${dkSaat(ss.bitis%1440)} geçti, çıkış kaydı yok`});
    }
  } else {
    if(!antraktCikismi(cikisDk)) {
      // Çıkış kontrolü:
      // Muafiyet SADECE geç çıkışa uygulanır: bitis ile (bitis + cikisToler) arası normal
      // Erken çıkış: bitis'ten önce her zaman hata (muafiyet yok)
      if(cikisDk < ss.bitis) {
        hatalar.push({tip:"ERKEN ÇIKIŞ", aciklama:`Vardiya ${dkSaat(ss.bitis%1440)} — Çıkış ${gCikis} (${ss.bitis-cikisDk} dk erken)`});
      }
      if(cikisDk > ss.bitis + cikisToler) {
        hatalar.push({tip:"GEÇ ÇIKIŞ", aciklama:`Vardiya ${dkSaat(ss.bitis%1440)} — Çıkış ${gCikis} (${cikisDk-ss.bitis} dk geç)`});
      }
    }
  }
  return hatalar;
};

// Örnek hareket verisi — birden fazla gün, farklı hatalar
const TUM_HAREKETLER = (() => {
  // Bugünün ISO tarihi — gerçek tarih
  const bugunIso = (() => {
    const n=new Date();
    return `${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,"0")}-${String(n.getDate()).padStart(2,"0")}`;
  })();
  const bugunTr = bugunIso.split("-").reverse().join(".");

  const saatEkle = (saat, dk) => {
    if(!saat) return "";
    const [h,m]=saat.split(":").map(Number);
    const total=h*60+m+dk;
    const yH=Math.floor(((total%1440)+1440)%1440/60);
    const yM=((total%1440)+1440)%1440%60;
    return `${String(yH).padStart(2,"0")}:${String(yM).padStart(2,"0")}`;
  };
  const rastgele = (hedef, muf) => {
    if(!hedef) return "";
    const dk=Math.floor(Math.random()*(muf+1));
    return saatEkle(hedef, Math.random()>0.25?-dk:dk);
  };

  // Bugünkü shift atamasını oku — yoksa varsayılan shift ata
  const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();
  const varsayilanShiftler = ["A","B","G","A","G","B","C","A","G","F","A","B"];

  return initPersonel.map((p,i) => {
    const shiftKod = shiftData[`${p.id}-${bugunIso}`] || varsayilanShiftler[i % varsayilanShiftler.length];
    const s = SHIFTS.find(x=>x.kod===shiftKod) || SHIFTS[0];

    // Bazı kişilere kasıtlı hata/eksik ekle — gerçekçilik için
    const hataSenaryosu = Math.random();
    let gGiris = "", gCikis = "";

    if(hataSenaryosu < 0.1) {
      // %10 — giriş yok
      gGiris = ""; gCikis = "";
    } else if(hataSenaryosu < 0.2) {
      // %10 — sadece giriş, çıkış yok
      gGiris = s.giris ? rastgele(s.giris, s.muafiyet||30) : "";
      gCikis = "";
    } else if(hataSenaryosu < 0.3) {
      // %10 — geç giriş (muafiyeti aşan)
      gGiris = s.giris ? saatEkle(s.giris, (s.muafiyet||30) + 10 + Math.floor(Math.random()*30)) : "";
      gCikis = s.cikis ? rastgele(s.cikis, s.cikisMuafiyet||30) : "";
    } else {
      // %70 — normal
      gGiris = s.giris ? rastgele(s.giris, s.muafiyet||30) : "";
      gCikis = s.cikis ? rastgele(s.cikis, s.cikisMuafiyet||30) : "";
    }

    const hatalar = hataDetect(shiftKod, gGiris, gCikis, bugunTr, bugunTr, s.muafiyet||30);
    return {
      id: p.id, ad: p.ad, soyad: p.soyad,
      departman: p.departman, gorev: p.gorev,
      tarih: bugunTr, shiftKod, gGiris, gCikis,
      hatalar, hatali: hatalar.length > 0,
      antract:"", aCikis:"", aGiris:"",
      mesai:"0.00", oTipi:"", oMesai:"0.00"
    };
  });
})();

// Bugünün tarihi (simüle)
// ─── GERÇEK TARİH ────────────────────────────────────────────────────────────
const GUNLER_TR = ["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"];
const AYLAR_TR = ["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"];
const pad2 = n => String(n).padStart(2,"0");
const _now = new Date();
const BUGUN_TARIH = `${pad2(_now.getDate())}.${pad2(_now.getMonth()+1)}.${_now.getFullYear()}`;
const BUGUN_ISO   = `${_now.getFullYear()}-${pad2(_now.getMonth()+1)}-${pad2(_now.getDate())}`;
const BUGUN_LABEL = `${pad2(_now.getDate())} ${AYLAR_TR[_now.getMonth()]} ${_now.getFullYear()} ${GUNLER_TR[_now.getDay()]}`;

// Haftanın pazartesisini bul (20.05.2026 için → 18.05.2026)
const haftaPazartesi = (tarihStr) => {
  const [g,a,y] = tarihStr.split(".").map(Number);
  const d = new Date(y,a-1,g);
  const gun = d.getDay(); // 0=Paz
  const fark = gun===0 ? 6 : gun-1;
  d.setDate(d.getDate()-fark);
  return `${String(d.getDate()).padStart(2,"0")}.${String(d.getMonth()+1).padStart(2,"0")}.${d.getFullYear()}`;
};

const tarihKarsilastir = (a, b) => {
  const parse = s => { const [g,ay,y]=s.split(".").map(Number); return new Date(y,ay-1,g).getTime(); };
  return parse(a)-parse(b);
};

const genHareketler = () => TUM_HAREKETLER;

// ─── HELPER ─────────────────────────────────────────────────────────────────
const avatarColors = ["#EEEDFE/#534AB7","#E1F5EE/#0F6E56","#FAECE7/#993C1D","#E6F1FB/#185FA5","#FAEEDA/#854F0B","#FBEAF0/#D4537E","#EAF3DE/#3B6D11","#F1EFE8/#5F5E5A"];
const getAvatarStyle = (i) => {
  const idx = Math.abs(parseInt(i) || 0) % avatarColors.length;
  const [bg,c] = (avatarColors[idx] || avatarColors[0]).split("/");
  return {background:bg, color:c};
};
const initials = (ad,soyad) => ((ad||"").charAt(0)+(soyad||"").charAt(0)).toUpperCase();
const shiftObj = (kod) => {
  const s = [...SHIFTS, ...IZINLER].find(x=>x.kod===kod);
  const varsayilan = VARSAYILAN_SHIFTS.find(x=>x.kod===kod);
  if(!s) return {kod, ad:kod, saat:"", renk:"#5F5E5A", bg:"#F1EFE8"};
  const saat = (s.giris && s.cikis) ? `${s.giris}-${s.cikis}` : (s.saat||"");
  // bg/renk yoksa VARSAYILAN_SHIFTS'ten al
  const bg = s.bg || varsayilan?.bg || "#F1EFE8";
  const renk = s.renk || varsayilan?.renk || "#5F5E5A";
  return {...s, saat, bg, renk};
};

// ─── EXCEL EXPORT (SheetJS) ──────────────────────────────────────────────────
const loadSheetJS = () => new Promise((resolve, reject) => {
  if(window.XLSX) { resolve(window.XLSX); return; }
  const s = document.createElement("script");
  s.src = "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";
  s.onload = () => resolve(window.XLSX);
  s.onerror = reject;
  document.head.appendChild(s);
});

const exportToExcel = async (rows, headers, filename="pdks_export.xlsx") => {
  try {
    const XLSX = await loadSheetJS();
    // rows: array of objects, headers: column order
    const data = [
      headers, // başlık satırı
      ...rows.map(row => headers.map(h => row[h] ?? ""))
    ];
    const ws = XLSX.utils.aoa_to_sheet(data);
    // Sütun genişliklerini otomatik ayarla
    ws["!cols"] = headers.map(h => ({
      wch: Math.max(h.length, ...rows.map(r => String(r[h]??"").length), 8)
    }));
    // Başlık satırını kalın yap
    headers.forEach((_,ci) => {
      const cell = XLSX.utils.encode_cell({r:0, c:ci});
      if(ws[cell]) ws[cell].s = {font:{bold:true}, fill:{fgColor:{rgb:"1565A0"}}, font2:{color:{rgb:"FFFFFF"}}};
    });
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Veri");
    XLSX.writeFile(wb, filename);
  } catch(e) {
    // Fallback: CSV
    const bom = "﻿";
    const esc = v => { const s=String(v??"").replace(/"/g,'""'); return s.includes(",")||s.includes("\n")?`"${s}"`:s; };
    const lines = [headers.join(","), ...rows.map(r=>headers.map(h=>esc(r[h]??"")).join(","))];
    const blob = new Blob([bom+lines.join("\n")],{type:"text/csv;charset=utf-8;"});
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href=url; a.download=filename.replace(".xlsx",".csv"); a.click();
    URL.revokeObjectURL(url);
  }
};

// ─── COMPONENTS ─────────────────────────────────────────────────────────────
const Badge = ({type,children}) => {
  const styles = {
    success:{background:"#EAF3DE",color:"#3B6D11"},
    danger:{background:"#FCEBEB",color:"#A32D2D"},
    warning:{background:"#FAEEDA",color:"#854F0B"},
    info:{background:"#E6F1FB",color:"#185FA5"},
    gray:{background:"#F1EFE8",color:"#5F5E5A"},
    purple:{background:"#EEEDFE",color:"#534AB7"},
  };
  return <span style={{...styles[type]||styles.gray,padding:"2px 8px",borderRadius:20,fontSize:11,fontWeight:500,display:"inline-flex",alignItems:"center"}}>{children}</span>;
};

const ShiftCell = ({kod}) => {
  if(!kod) return <span style={{color:"var(--text-tertiary)",fontSize:12}}>—</span>;
  const s = shiftObj(kod);
  return <span style={{background:s.bg,color:s.renk,padding:"2px 7px",borderRadius:4,fontSize:11,fontWeight:500,display:"inline-block"}}>{kod}</span>;
};

const Modal = ({title,onClose,children,footer,width=560}) => (
  <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,0.4)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:200}}>
    <div style={{background:"var(--card-bg)",borderRadius:12,border:"0.5px solid var(--grid-line)",width,maxHeight:"90vh",overflow:"auto",display:"flex",flexDirection:"column"}}>
      <div style={{padding:"14px 20px",borderBottom:"0.5px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center",flexShrink:0}}>
        <span style={{fontWeight:500,fontSize:15}}>{title}</span>
        <button onClick={onClose} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-secondary)",fontSize:18,padding:"0 4px"}}>✕</button>
      </div>
      <div style={{padding:20,overflowY:"auto",flex:1}}>{children}</div>
      {footer && <div style={{padding:"12px 20px",borderTop:"0.5px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8,flexShrink:0}}>{footer}</div>}
    </div>
  </div>
);

const Btn = ({onClick,primary,danger,children,style={}}) => (
  <button onClick={onClick} style={{
    padding:"6px 14px",borderRadius:8,
    border:`1px solid ${primary?"#5349B7":danger?"#A32D2D":"var(--input-border)"}`,
    background:primary?"#5349B7":danger?"#FCEBEB":"transparent",
    color:primary?"#fff":danger?"#A32D2D":"var(--text-primary)",
    fontSize:12,fontWeight:500,cursor:"pointer",
    display:"inline-flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:2,
    fontFamily:"var(--font-sans)",letterSpacing:"0.01em",
    whiteSpace:"nowrap",flexShrink:0,minHeight:48,
    ...style
  }}>{children}</button>
);

const FormRow = ({label,children}) => (
  <div style={{marginBottom:12}}>
    <div style={{fontSize:12,color:"var(--text-secondary)",marginBottom:4}}>{label}</div>
    {children}
  </div>
);

const Input = ({value,onChange,placeholder,type="text",style={}}) => (
  <input type={type} value={value} onChange={onChange} placeholder={placeholder} style={{width:"100%",padding:"7px 10px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",fontFamily:"var(--font-sans)",...style}} />
);

// Tarih girişi — nokta koymadan yazılınca otomatik GG.MM.YYYY formatlar
const DateInput = ({value, onChange, placeholder="GG.MM.YYYY", style={}}) => {
  const formatTarih = (raw) => {
    // Sadece rakamları al
    const digits = raw.replace(/\D/g,"");
    if(digits.length === 0) return "";
    if(digits.length <= 2) return digits;
    if(digits.length <= 4) return `${digits.slice(0,2)}.${digits.slice(2)}`;
    if(digits.length <= 8) return `${digits.slice(0,2)}.${digits.slice(2,4)}.${digits.slice(4)}`;
    // 8 rakamdan fazla → kırp
    return `${digits.slice(0,2)}.${digits.slice(2,4)}.${digits.slice(4,8)}`;
  };

  const handleChange = (e) => {
    const raw = e.target.value;
    // Eğer kullanıcı siliyor (length azaldı) — formatlamadan geç
    const digits = raw.replace(/\D/g,"");
    const formatted = formatTarih(raw);
    onChange({target:{value:formatted}});
  };

  const handleBlur = (e) => {
    // Blur'da da formatla
    const formatted = formatTarih(e.target.value);
    onChange({target:{value:formatted}});
  };

  return (
    <input
      type="text"
      value={value||""}
      onChange={handleChange}
      onBlur={handleBlur}
      placeholder={placeholder}
      maxLength={10}
      style={{width:"100%",padding:"7px 10px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",fontFamily:"monospace",...style}}
    />
  );
};

const Select = ({value,onChange,children,style={}}) => (
  <select value={value} onChange={onChange} style={{width:"100%",padding:"7px 10px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",fontFamily:"var(--font-sans)",...style}}>{children}</select>
);

// ─── EXCEL TOPLU AKTARIM ─────────────────────────────────────────────────────
// Alan eşleştirme: Excel başlığı → personel nesnesindeki key
const EXCEL_ALAN_MAP = {
  // Kimlik
  "TC KİMLİK NO": "tc", "TC": "tc", "TC KİMLİK": "tc", "KİMLİK NO": "tc",
  // Temel
  "SİCİL NO": "sicil", "SİCİL": "sicil",
  "ADI": "ad", "AD": "ad",
  "SOYADI": "soyad", "SOYAD": "soyad",
  "DEPARTMAN": "departman",
  "GÖREV": "gorev", "GÖREV/UNVAN": "gorev",
  "ÇALIŞMA GRUBU": "calismaGrubu",
  // Tarihler
  "İŞE GİRİŞ": "isGiris", "İŞE GİRİŞ TARİHİ": "isGiris",
  "İŞTEN ÇIKIŞ": "istenCikis", "İŞTEN ÇIKIŞ TARİHİ": "istenCikis",
  "ŞİRKET GİRİŞ": "sirketGiris",
  "SSK BAŞLANGIÇ": "sskTar",
  // İletişim
  "TELEFON": "telefon", "CEP TELEFONU": "telefon",
  "DOĞUM TARİHİ": "dogumTarihi", "DOĞUM": "dogumTarihi",
  "KAN GRUBU": "kanGrubu",
  // Maaş
  "NET ÜCRET": "maas", "MAAŞ": "maas", "NET MAAŞ": "maas", "ÜCRETİ": "maas",
  // Diğer
  "CİHAZ NO": "cihazNo", "DOLAP NO": "dolapNo", "LOJMAN NO": "lojmanNo",
  "SGK NO": "sgkNo", "BORDRO SİCİL": "bordroSicil",
  "ÖĞRENİM": "ogrenim", "DURUM": "durum",
  "DEVAM KONTROLÜ": "devamKontrol",
};

const ExcelImport = ({personeller, onClose, onSave}) => {
  const [step, setStep] = useState(1); // 1=yükle, 2=önizleme, 3=sonuç
  const [rawRows, setRawRows] = useState([]);
  const [headers, setHeaders] = useState([]);
  const [mapped, setMapped] = useState({}); // colIdx → fieldKey
  const [preview, setPreview] = useState([]);
  const [sonuc, setSonuc] = useState(null);
  const fileRef = useRef();

  const loadSheetJS = () => new Promise((res,rej) => {
    if(window.XLSX){res(window.XLSX);return;}
    const s=document.createElement("script");
    s.src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";
    s.onload=()=>res(window.XLSX); s.onerror=rej;
    document.head.appendChild(s);
  });

  const handleFile = async (e) => {
    const file = e.target.files[0];
    if(!file) return;
    const XLSX = await loadSheetJS();
    const data = await file.arrayBuffer();
    const wb = XLSX.read(data);
    const ws = wb.Sheets[wb.SheetNames[0]];
    const rows = XLSX.utils.sheet_to_json(ws, {header:1, defval:""});
    if(!rows.length) return;
    const hdrs = rows[0].map(h => String(h).trim().toUpperCase());
    setHeaders(hdrs);
    setRawRows(rows.slice(1).filter(r => r.some(c=>c!=="")));
    // Otomatik eşleştir
    const autoMap = {};
    hdrs.forEach((h,i) => { if(EXCEL_ALAN_MAP[h]) autoMap[i] = EXCEL_ALAN_MAP[h]; });
    setMapped(autoMap);
    setStep(2);
  };

  // Excel serial date → GG.MM.YYYY
  const excelSerialToTr = (val) => {
    const n = Number(val);
    if(isNaN(n) || n < 1) return String(val||"").trim();
    // Excel epoch: 1 Jan 1900 = serial 1 (with leap year bug: serial 60 = 29 Feb 1900 skip)
    const utc = new Date(Date.UTC(1899, 11, 30) + n * 86400000);
    const g = String(utc.getUTCDate()).padStart(2,"0");
    const m = String(utc.getUTCMonth()+1).padStart(2,"0");
    const y = utc.getUTCFullYear();
    return `${g}.${m}.${y}`;
  };

  // Tarih alanı key listesi
  const TARIH_ALANLARI = new Set(["isGiris","istenCikis","sirketGiris","sskTar","dogumTarihi"]);

  const normalizeVal = (fk, raw) => {
    const str = String(raw||"").trim();
    if(!TARIH_ALANLARI.has(fk)) {
      // Maaş alanı: sayıya çevir (binlik ayraç temizle)
      if(fk === "maas" && str) {
        const temiz = str.replace(/[.,\s]/g, (m,i,s) => {
          // Türkçe binlik ayraç (.) veya Avrupa formatı (,) temizle
          // "35.000" → 35000, "35,000" → 35000, "35000" → 35000
          return "";
        });
        const n = Number(str.replace(/\./g,"").replace(/,/g,"."));
        // "35.000" → remove dots → 35000; "35,000" → 35000; "35000.50" → 35000
        const cleaned = str.replace(/\./g,"").replace(/,\d{3}/g, m=>m.slice(1));
        return Number(str.replace(/[^\d]/g,"")) || 0;
      }
      return str;
    }
    if(!str || str==="0") return "";
    // Zaten GG.MM.YYYY formatında mı?
    if(/^\d{2}\.\d{2}\.\d{4}$/.test(str)) return str;
    // YYYY-MM-DD formatı (ISO)?
    if(/^\d{4}-\d{2}-\d{2}/.test(str)) {
      const [y,m,g] = str.slice(0,10).split("-");
      return `${g}.${m}.${y}`;
    }
    // Sadece rakam (8 hane): DDMMYYYY
    if(/^\d{8}$/.test(str)) return `${str.slice(0,2)}.${str.slice(2,4)}.${str.slice(4)}`;
    // Excel serial number (sayı, 5 haneden fazla)
    if(/^\d{4,6}$/.test(str)) return excelSerialToTr(str);
    // JavaScript Date string?
    const d = new Date(str);
    if(!isNaN(d.getTime())) {
      const g = String(d.getDate()).padStart(2,"0");
      const m = String(d.getMonth()+1).padStart(2,"0");
      return `${g}.${m}.${d.getFullYear()}`;
    }
    return str;
  };

  const buildPreview = () => {
    const rows = rawRows.map(row => {
      const obj = {};
      Object.entries(mapped).forEach(([ci,fk]) => {
        obj[fk] = normalizeVal(fk, row[ci]);
      });
      const mevcut = obj.tc ? personeller.find(p=>p.tc===obj.tc) : null;
      return {...obj, _mevcut: mevcut, _eylem: mevcut ? "güncelle" : "ekle"};
    });
    setPreview(rows);
    setStep(3);
  };

  const aktar = () => {
    let eklenen=0, guncellenen=0, atlanan=0;
    const yeniListe = [...personeller];
    preview.forEach(row => {
      const {_mevcut, _eylem, ...data} = row;
      if(!data.tc && !data.sicil) { atlanan++; return; }
      if(_eylem === "güncelle" && _mevcut) {
        const idx = yeniListe.findIndex(p=>p.id===_mevcut.id);
        if(idx>=0) { yeniListe[idx]={..._mevcut,...data, id:_mevcut.id}; guncellenen++; }
      } else if(_eylem === "ekle") {
        yeniListe.push({...Object.fromEntries(Object.entries({
          id:Date.now()+Math.random(),sicil:"",tc:"",ad:"",soyad:"",departman:DEPARTMANLAR[0],gorev:GOREVLER[0],
          calismaGrubu:"NOR. ÇL.",isGiris:"",istenCikis:"",durum:"Çalışıyor",telefon:"",dogumTarihi:"",
          kanGrubu:"",maas:0,cihazNo:"",dolapNo:"",lojmanNo:"",sgkNo:"",sskTar:"",sirketGiris:"",
          devamKontrol:"Yapılacak",servis:"",durak:"",hesDoku:"",bordroSicil:"",ogrenim:"",acilGrup:"",
          uiDevir:0,yiDevir:0,notlar:""
        })),...data}); eklenen++;
      }
    });
    onSave(yeniListe);
    setSonuc({eklenen, guncellenen, atlanan});
    setStep(4);
  };

  const indirSablon = async () => {
    const XLSX = await loadSheetJS();
    const sablon = [
      ["TC KİMLİK NO","SİCİL NO","ADI","SOYADI","DEPARTMAN","GÖREV","İŞE GİRİŞ","NET ÜCRET","TELEFON","DOĞUM TARİHİ","KAN GRUBU","DURUM"],
      ["12345678901","M.001.0001","AHMET","YILMAZ","ANİMASYON","Animatör","01.05.2025","35000","0532 111 22 33","01.01.1990","A+","Çalışıyor"],
    ];
    const ws = XLSX.utils.aoa_to_sheet(sablon);
    ws["!cols"] = sablon[0].map(()=>({wch:18}));
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Personel");
    XLSX.writeFile(wb, "personel_sablon.xlsx");
  };

  return (
    <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:400}}>
      <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:780,maxHeight:"85vh",display:"flex",flexDirection:"column"}}>
        {/* Başlık */}
        <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
          <div>
            <div style={{fontWeight:600,fontSize:15}}>📥 Excel'den Toplu Aktarım</div>
            <div style={{fontSize:11,color:"var(--text-tertiary)",marginTop:2}}>TC Kimlik No ile eşleştirme · Yeni ekleme veya güncelleme</div>
          </div>
          <div style={{display:"flex",gap:8,alignItems:"center"}}>
            {/* Adım göstergesi */}
            {["Yükle","Eşleştir","Önizleme","Sonuç"].map((s,i)=>(
              <div key={s} style={{display:"flex",alignItems:"center",gap:4}}>
                <span style={{width:20,height:20,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,fontWeight:600,background:step>i?"#1565A0":step===i+1?"#1565A0":"var(--input-bg)",color:step>=i+1?"#fff":"var(--text-tertiary)"}}>{i+1}</span>
                <span style={{fontSize:11,color:step===i+1?"var(--text-primary)":"var(--text-tertiary)"}}>{s}</span>
                {i<3 && <span style={{color:"var(--grid-line)"}}>›</span>}
              </div>
            ))}
            <button onClick={onClose} style={{marginLeft:8,background:"none",border:"none",cursor:"pointer",color:"var(--text-secondary)",fontSize:18}}>✕</button>
          </div>
        </div>

        <div style={{flex:1,overflow:"auto",padding:20}}>
          {/* ADIM 1: Dosya yükle */}
          {step===1 && (
            <div style={{textAlign:"center"}}>
              <div style={{padding:40,border:"2px dashed var(--input-border)",borderRadius:12,marginBottom:16,cursor:"pointer"}}
                onClick={()=>fileRef.current.click()}>
                <div style={{fontSize:40,marginBottom:12}}>📊</div>
                <div style={{fontSize:15,fontWeight:500,marginBottom:6}}>Excel dosyası seçin</div>
                <div style={{fontSize:12,color:"var(--text-tertiary)"}}>xlsx veya xls formatı · İlk satır başlık olmalı</div>
              </div>
              <input ref={fileRef} type="file" accept=".xlsx,.xls,.csv" style={{display:"none"}} onChange={handleFile} />
              <div style={{display:"flex",gap:12,justifyContent:"center",flexWrap:"wrap"}}>
                <Btn primary onClick={()=>fileRef.current.click()}>📂 Dosya Seç</Btn>
                <Btn onClick={indirSablon}>⬇️ Şablon İndir</Btn>
              </div>
              <div style={{marginTop:20,padding:14,background:"var(--input-bg)",borderRadius:8,textAlign:"left",fontSize:12,color:"var(--text-secondary)"}}>
                <div style={{fontWeight:600,marginBottom:8,color:"var(--text-primary)"}}>Tanınan sütun başlıkları:</div>
                <div style={{display:"flex",flexWrap:"wrap",gap:4}}>
                  {Object.keys(EXCEL_ALAN_MAP).map(k=><span key={k} style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:4,padding:"2px 6px",fontSize:11}}>{k}</span>)}
                </div>
              </div>
            </div>
          )}

          {/* ADIM 2: Sütun eşleştirme */}
          {step===2 && (
            <div>
              <div style={{marginBottom:14,fontSize:13,color:"var(--text-secondary)"}}>{rawRows.length} satır bulundu. Sütunları eşleştirin:</div>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:16}}>
                {headers.map((h,i)=>(
                  <div key={i} style={{display:"flex",alignItems:"center",gap:8,padding:"8px 10px",background:"var(--input-bg)",borderRadius:8,fontSize:12}}>
                    <span style={{flex:1,fontWeight:500,color:"var(--text-primary)"}}>{h}</span>
                    <span style={{color:"var(--text-tertiary)"}}>→</span>
                    <select value={mapped[i]||""} onChange={e=>{const n={...mapped};if(e.target.value)n[i]=e.target.value;else delete n[i];setMapped(n);}}
                      style={{padding:"4px 6px",border:"1px solid var(--input-border)",borderRadius:4,background:"var(--card-bg)",color:"var(--text-primary)",fontSize:11,maxWidth:160}}>
                      <option value="">— Atla —</option>
                      {Object.entries({tc:"TC Kimlik",sicil:"Sicil No",ad:"Ad",soyad:"Soyad",departman:"Departman",gorev:"Görev",isGiris:"İşe Giriş",istenCikis:"İşten Çıkış",maas:"Net Ücret",telefon:"Telefon",dogumTarihi:"Doğum",kanGrubu:"Kan Grubu",durum:"Durum",cihazNo:"Cihaz No",dolapNo:"Dolap",lojmanNo:"Lojman",sgkNo:"SGK No",ogrenim:"Öğrenim",calismaGrubu:"Çalışma Grubu",devamKontrol:"Devam Kontrolü"}).map(([v,l])=>(
                        <option key={v} value={v}>{l}</option>
                      ))}
                    </select>
                  </div>
                ))}
              </div>
              <div style={{padding:10,background:"#EAF3DE",border:"1px solid #3B6D11",borderRadius:8,fontSize:12,color:"#3B6D11",marginBottom:12}}>
                ✓ TC Kimlik eşleşirse mevcut personel güncellenir. Eşleşmezse yeni kayıt oluşturulur.
              </div>
            </div>
          )}

          {/* ADIM 3: Önizleme */}
          {step===3 && (
            <div>
              <div style={{display:"flex",gap:12,marginBottom:12}}>
                <span style={{background:"#EAF3DE",color:"#3B6D11",padding:"3px 10px",borderRadius:20,fontSize:12,fontWeight:600}}>+ {preview.filter(r=>r._eylem==="ekle").length} yeni eklenecek</span>
                <span style={{background:"#E6F1FB",color:"#185FA5",padding:"3px 10px",borderRadius:20,fontSize:12,fontWeight:600}}>↺ {preview.filter(r=>r._eylem==="güncelle").length} güncellenecek</span>
              </div>
              <div style={{overflowX:"auto"}}>
                <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
                  <thead><tr>
                    <th>İşlem</th>
                    <th>TC</th>
                    <th>Ad Soyad</th>
                    <th>Departman</th>
                    <th>Net Ücret</th>
                    {Object.values(mapped).filter(v=>!["tc","ad","soyad","departman","maas"].includes(v)).slice(0,4).map(v=><th key={v}>{v}</th>)}
                  </tr></thead>
                  <tbody>
                    {preview.map((r,i)=>(
                      <tr key={i}>
                        <td><span style={{background:r._eylem==="ekle"?"#EAF3DE":"#E6F1FB",color:r._eylem==="ekle"?"#3B6D11":"#185FA5",padding:"2px 8px",borderRadius:20,fontSize:11,fontWeight:600}}>{r._eylem==="ekle"?"+ YENİ":"↺ GÜNCELLE"}</span></td>
                        <td style={{fontFamily:"monospace",fontSize:11}}>{r.tc||"—"}</td>
                        <td style={{fontWeight:500}}>{r.ad} {r.soyad}</td>
                        <td style={{color:"var(--text-secondary)"}}>{r.departman||"—"}</td>
                        <td>{r.maas?`${Number(r.maas).toLocaleString("tr-TR")} ₺`:"—"}</td>
                        {Object.values(mapped).filter(v=>!["tc","ad","soyad","departman","maas"].includes(v)).slice(0,4).map(v=><td key={v} style={{color:"var(--text-secondary)"}}>{r[v]||"—"}</td>)}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          )}

          {/* ADIM 4: Sonuç */}
          {step===4 && sonuc && (
            <div style={{textAlign:"center",padding:32}}>
              <div style={{fontSize:40,marginBottom:16}}>✅</div>
              <div style={{fontSize:18,fontWeight:600,marginBottom:16}}>Aktarım Tamamlandı</div>
              <div style={{display:"flex",gap:16,justifyContent:"center",flexWrap:"wrap"}}>
                <div style={{background:"#EAF3DE",border:"1px solid #3B6D11",borderRadius:8,padding:"12px 20px",minWidth:100}}>
                  <div style={{fontSize:28,fontWeight:700,color:"#3B6D11"}}>{sonuc.eklenen}</div>
                  <div style={{fontSize:12,color:"#3B6D11"}}>Yeni Eklendi</div>
                </div>
                <div style={{background:"#E6F1FB",border:"1px solid #185FA5",borderRadius:8,padding:"12px 20px",minWidth:100}}>
                  <div style={{fontSize:28,fontWeight:700,color:"#185FA5"}}>{sonuc.guncellenen}</div>
                  <div style={{fontSize:12,color:"#185FA5"}}>Güncellendi</div>
                </div>
                {sonuc.atlanan>0 && <div style={{background:"#FAEEDA",border:"1px solid #854F0B",borderRadius:8,padding:"12px 20px",minWidth:100}}>
                  <div style={{fontSize:28,fontWeight:700,color:"#854F0B"}}>{sonuc.atlanan}</div>
                  <div style={{fontSize:12,color:"#854F0B"}}>Atlandı (TC/Sicil yok)</div>
                </div>}
              </div>
            </div>
          )}
        </div>

        {/* Altbar */}
        <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
          {step===1 && <Btn onClick={onClose}>İptal</Btn>}
          {step===2 && <>
            <Btn onClick={()=>setStep(1)}>← Geri</Btn>
            <Btn primary onClick={buildPreview} disabled={!Object.values(mapped).length}>Önizlemeye Geç →</Btn>
          </>}
          {step===3 && <>
            <Btn onClick={()=>setStep(2)}>← Geri</Btn>
            <Btn primary onClick={aktar}>⚡ Aktarımı Başlat ({preview.length} kayıt)</Btn>
          </>}
          {step===4 && <Btn primary onClick={onClose}>Kapat</Btn>}
        </div>
      </div>
    </div>
  );
};

// ─── ERROR BOUNDARY ──────────────────────────────────────────────────────────
class ErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = {hata:null}; }
  static getDerivedStateFromError(e) { return {hata:e}; }
  render() {
    if(this.state.hata) return (
      <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:999}}>
        <div style={{background:"#151c2c",border:"1px solid #A32D2D",borderRadius:12,padding:32,maxWidth:520,width:"90%"}}>
          <div style={{color:"#f87171",fontWeight:700,fontSize:16,marginBottom:12}}>⚠️ Personel kartı açılamadı</div>
          <div style={{fontFamily:"monospace",fontSize:11,color:"#94a3b8",background:"#0f1520",padding:12,borderRadius:6,marginBottom:16,wordBreak:"break-all",maxHeight:120,overflowY:"auto"}}>
            {this.state.hata?.message || String(this.state.hata)}
          </div>
          <button onClick={()=>{this.setState({hata:null});this.props.onClose?.();}}
            style={{padding:"8px 20px",background:"#1565A0",color:"#fff",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,fontFamily:"sans-serif"}}>
            Kapat
          </button>
        </div>
      </div>
    );
    return this.props.children;
  }
}

const PersonelKartiSafe = (props) => (
  <ErrorBoundary onClose={props.onClose}>
    <PersonelKarti {...props} />
  </ErrorBoundary>
);

const PersonelKarti = ({p, onClose, onSave, aktifKullanici=null}) => {
  const [tab, setTab] = useState("genel");
  // Tüm alanlar için güvenli varsayılanlar — undefined/null crash'i önle
  const safeP = {
    id: p.id ?? Date.now(),
    sicil: p.sicil ?? "", tc: p.tc ?? "", ad: p.ad ?? "", soyad: p.soyad ?? "",
    departman: p.departman ?? DEPARTMANLAR[0], gorev: p.gorev ?? "",
    calismaGrubu: p.calismaGrubu ?? "NOR. ÇL.", acilGrup: p.acilGrup ?? "",
    ogrenim: p.ogrenim ?? "", telefon: p.telefon ?? "",
    dogumTarihi: p.dogumTarihi ?? "", kanGrubu: p.kanGrubu ?? "",
    cihazNo: p.cihazNo ?? "", dolapNo: p.dolapNo ?? "", lojmanNo: p.lojmanNo ?? "",
    servis: p.servis ?? "", durak: p.durak ?? "", hesDoku: p.hesDoku ?? "",
    bordroSicil: p.bordroSicil ?? "",
    tc2: p.tc2 ?? "", sgkNo: p.sgkNo ?? "", sskTar: p.sskTar ?? "",
    isGiris: p.isGiris ?? "", istenCikis: p.istenCikis ?? "",
    sirketGiris: p.sirketGiris ?? "", durum: p.durum ?? "Çalışıyor",
    devamKontrol: p.devamKontrol ?? "Yapılacak",
    maas: p.maas ?? 0, uiDevir: p.uiDevir ?? 0, yiDevir: p.yiDevir ?? 0,
    notlar: p.notlar ?? "",
  };
  const [form, setForm] = useState(safeP);
  const f = (k) => (v) => setForm(prev=>({...prev,[k]:typeof v==="object"?v.target.value:v}));

  // Net → Brüt hesaplama (Türkiye 2024 vergi dilimi basit)
  // Net = Brüt - SGK(%14) - İşsizlik(%1) - GelirVergisi(%20) - DamgaVergisi(%0.759)
  // Brüt = Net / (1 - 0.14 - 0.01 - 0.20 - 0.00759) = Net / 0.64241
  const netMaasGirilen = Number(form.maas) || 0;
  const brutMaas = Math.round(netMaasGirilen / 0.64241);
  const sgk = Math.round(brutMaas * 0.14);
  const issizlik = Math.round(brutMaas * 0.01);
  const gelirV = Math.round(brutMaas * 0.20);
  const damgaV = Math.round(brutMaas * 0.00759);
  const netKontrol = brutMaas - sgk - issizlik - gelirV - damgaV;

  // Devam kontrolü "Yapılmayacak" ise günlük hareketleri otomatik doldur
  const devamKontrolYapilmayacak = form.devamKontrol === "Yapılmayacak";
  const [autoFillMsg, setAutoFillMsg] = useState("");
  const autoFillHareketler = () => {
    const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();
    const hareketData = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):null; } catch{return null;} })();
    if(!hareketData) { setAutoFillMsg("Henüz hareket verisi yok."); return; }
    const saatEkle = (saat, dk) => {
      if(!saat) return "";
      const [h,m]=saat.split(":").map(Number); const total=h*60+m+dk;
      const yH=Math.floor(((total%1440)+1440)%1440/60); const yM=((total%1440)+1440)%1440%60;
      return `${String(yH).padStart(2,"0")}:${String(yM).padStart(2,"0")}`;
    };
    const rastgele = (hedef, muf) => { if(!hedef) return ""; const dk=Math.floor(Math.random()*(muf+1)); return saatEkle(hedef, Math.random()>0.3?-dk:dk); };
    const yeni = hareketData.map(h => {
      if(h.id !== form.id) return h;
      const s = shiftObj(h.shiftKod);
      if(!s.giris) return h;
      const yeniGiris = h.gGiris||rastgele(s.giris, s.muafiyet||30);
      const yeniCikis = h.gCikis||rastgele(s.cikis, s.cikisMuafiyet||30);
      return {...h, gGiris:yeniGiris, gCikis:yeniCikis};
    });
    localStorage.setItem("pdks_hareketler", JSON.stringify(yeni));
    setAutoFillMsg(`✓ ${form.ad} ${form.soyad} için hareketler otomatik dolduruldu.`);
  };

  // KVKK alan kontrolü — kullanıcı yetkisinde gizli alanlar maskelenir
  const isAdmin = aktifKullanici?.yetki === "admin";
  const alanIzinleri = getGuncelAlanIzinleri();
  const alanGoster = (alanKey) => {
    if(isAdmin) return true;
    return alanIzinleri[alanKey]?.goster === true;
  };
  const maskele = (deger, alanKey) => {
    if(alanGoster(alanKey)) return deger;
    if(!deger) return "—";
    return "••••••";
  };
  const fotoKey = `pdks_foto_${form.sicil||form.id}`;
  const [foto, setFoto] = useState(() => {
    try { return localStorage.getItem(fotoKey)||null; } catch { return null; }
  });
  const fotoInputRef = useRef();

  const handleFotoUpload = (e) => {
    const file = e.target.files[0];
    if(!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      const dataUrl = ev.target.result;
      setFoto(dataUrl);
      try { localStorage.setItem(fotoKey, dataUrl); } catch {}
    };
    reader.readAsDataURL(file);
  };

  const silPersonel = () => {
    if(!confirm("EVET yazın ve onaylayın — bu personeli silmek istediğinizden emin misiniz?\n\nDikkat: Bu işlem geri alınamaz!")) return;
    const onay = prompt('Silmek için "EVET" yazın:');
    if(onay?.trim().toUpperCase() !== "EVET") { alert("Silme iptal edildi."); return; }
    onSave(null); // null = sil sinyali
    onClose();
  };

  return (
    <Modal title="Personel Kartı" onClose={onClose} width={680}
      footer={<>
        <Btn danger onClick={silPersonel} style={{marginRight:"auto"}}>Personeli Sil</Btn>
        <Btn onClick={onClose}>Kapat</Btn>
        <Btn primary onClick={()=>onSave(form)}><span style={{fontSize:16}}>💾</span><span>Kaydet [F2]</span></Btn>
      </>}>
      <div style={{display:"flex",gap:16,alignItems:"center",marginBottom:20,padding:"12px 16px",background:"var(--input-bg)",borderRadius:8}}>
        {/* Fotoğraf alanı */}
        <div style={{position:"relative",flexShrink:0}}>
          {foto
            ? <img src={foto} alt="foto" style={{width:60,height:60,borderRadius:"50%",objectFit:"cover",border:"2px solid var(--grid-line)"}} />
            : <div style={{...getAvatarStyle(form.id),width:60,height:60,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,fontWeight:500}}>{initials(form.ad,form.soyad)}</div>
          }
          <button onClick={()=>fotoInputRef.current?.click()}
            title="Fotoğraf yükle"
            style={{position:"absolute",bottom:-2,right:-2,width:20,height:20,borderRadius:"50%",background:"#1565A0",border:"2px solid var(--card-bg)",color:"#fff",fontSize:10,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",padding:0}}>
            +
          </button>
          <input ref={fotoInputRef} type="file" accept="image/*" style={{display:"none"}} onChange={handleFotoUpload} />
        </div>
        <div style={{flex:1}}>
          <div style={{fontSize:17,fontWeight:500}}>{form.ad||"Yeni Personel"} {form.soyad}</div>
          <div style={{fontSize:13,color:"var(--text-secondary)",marginTop:2}}>{form.gorev||"—"} · {form.departman}</div>
          <div style={{marginTop:6,display:"flex",gap:6,flexWrap:"wrap"}}>
            <Badge type={form.durum==="Çalışıyor"?"success":"gray"}>{form.durum||"Çalışıyor"}</Badge>
            {form.sicil && <span style={{fontSize:11,background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",padding:"2px 8px",borderRadius:20,color:"var(--text-secondary)"}}>Sicil: {form.sicil}</span>}
          </div>
        </div>
      </div>
      {/* Tabs */}
      <div style={{display:"flex",gap:2,padding:4,background:"var(--input-bg)",borderRadius:8,marginBottom:16,width:"fit-content",flexWrap:"wrap"}}>
        {[["genel","Genel Bilgi"],["sosyal","Sosyal Güvenlik"],["calisma","Çalışma"],["maas","Maaş"],["izin","İzin Devirleri"],["notlar","Notlar"]].map(([k,l])=>(
          <button key={k} onClick={()=>setTab(k)} style={{padding:"5px 12px",borderRadius:6,fontSize:12,border:tab===k?"0.5px solid var(--grid-line)":"none",background:tab===k?"var(--card-bg)":"transparent",fontWeight:tab===k?500:400,cursor:"pointer",color:"var(--text-primary)",fontFamily:"var(--font-sans)"}}>{l}</button>
        ))}
      </div>

      {tab==="genel" && (
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
          <FormRow label="Adı"><Input value={form.ad} onChange={f("ad")} /></FormRow>
          <FormRow label="Soyadı"><Input value={form.soyad} onChange={f("soyad")} /></FormRow>
          <FormRow label="Departman"><Select value={form.departman} onChange={f("departman")}>{getDepartmanlar().map(d=><option key={d.ad} value={d.ad}>{d.ad}</option>)}</Select></FormRow>
          <FormRow label="Görevi">
            <Select value={form.gorev} onChange={f("gorev")}>
              {form.gorev && !getGorevlerForDept(form.departman).find(g=>g.ad===form.gorev) && (
                <option value={form.gorev}>{form.gorev}</option>
              )}
              {getGorevlerForDept(form.departman).map(g=><option key={g.ad} value={g.ad}>{g.ad}</option>)}
              {getGorevlerForDept(form.departman).length===0 && <option value="">— Bu departmana görev eklenmemiş —</option>}
            </Select>
          </FormRow>
          <FormRow label="Çalışma Grubu"><Input value={form.calismaGrubu} onChange={f("calismaGrubu")} /></FormRow>
          <FormRow label="Acil Durum Grubu"><Input value={form.acilGrup} onChange={f("acilGrup")} /></FormRow>
          <FormRow label="Öğrenim Durumu"><Select value={form.ogrenim} onChange={f("ogrenim")}><option value="">Seçiniz</option>{["İlkokul","Ortaokul","Lise","Ön Lisans","Üniversite","Yüksek Lisans","Doktora"].map(o=><option key={o}>{o}</option>)}</Select></FormRow>
          <FormRow label="Telefon Numarası">
            {alanGoster("personel_telefon") ? <Input value={form.telefon} onChange={f("telefon")} /> : <div style={{padding:"7px 10px",background:"var(--input-bg)",borderRadius:8,fontSize:13,color:"var(--text-tertiary)",border:"0.5px solid var(--input-border)"}}>••••••••••</div>}
          </FormRow>
          <FormRow label="Doğum Tarihi">
            {alanGoster("personel_dogum") ? <DateInput value={form.dogumTarihi} onChange={f("dogumTarihi")} /> : <div style={{padding:"7px 10px",background:"var(--input-bg)",borderRadius:8,fontSize:13,color:"var(--text-tertiary)",border:"0.5px solid var(--input-border)"}}>••••••••••</div>}
          </FormRow>
          <FormRow label="Kan Grubu">
            {alanGoster("personel_kan") ? <Select value={form.kanGrubu} onChange={f("kanGrubu")}><option value="">Seçiniz</option>{["A+","A-","B+","B-","AB+","AB-","0+","0-"].map(k=><option key={k}>{k}</option>)}</Select> : <div style={{padding:"7px 10px",background:"var(--input-bg)",borderRadius:8,fontSize:13,color:"var(--text-tertiary)",border:"0.5px solid var(--input-border)"}}>••</div>}
          </FormRow>
          <FormRow label="Cihaz Kayıt No"><Input value={form.cihazNo} onChange={f("cihazNo")} /></FormRow>
          <FormRow label="Dolap No"><Input value={form.dolapNo} onChange={f("dolapNo")} /></FormRow>
          <FormRow label="Lojman No"><Input value={form.lojmanNo} onChange={f("lojmanNo")} /></FormRow>
          <FormRow label="Servis"><Input value={form.servis} onChange={f("servis")} /></FormRow>
          <FormRow label="Durak"><Input value={form.durak} onChange={f("durak")} /></FormRow>
          <FormRow label="HES Kodu"><Input value={form.hesDoku} onChange={f("hesDoku")} /></FormRow>
          <FormRow label="Bordro Sicil No"><Input value={form.bordroSicil} onChange={f("bordroSicil")} /></FormRow>
        </div>
      )}

      {tab==="sosyal" && (
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
          <FormRow label="TC Kimlik No">
            {alanGoster("personel_tc") ? <Input value={form.tc} onChange={f("tc")} /> : <div style={{padding:"7px 10px",background:"var(--input-bg)",borderRadius:8,fontSize:13,color:"var(--text-tertiary)",border:"0.5px solid var(--input-border)",fontFamily:"monospace",letterSpacing:2}}>•••••••••••</div>}
          </FormRow>
          <FormRow label="Sos.Güv.No"><Input value={form.sgkNo} onChange={f("sgkNo")} /></FormRow>
          <FormRow label="SSK Başlangıç Tarihi"><DateInput value={form.sskTar} onChange={f("sskTar")} /></FormRow>
          <div />
        </div>
      )}

      {tab==="calisma" && (
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
          <FormRow label="İşe Giriş Tarihi"><DateInput value={form.isGiris} onChange={f("isGiris")} /></FormRow>
          <FormRow label="İşten Çıkış Tarihi"><DateInput value={form.istenCikis} onChange={f("istenCikis")} /></FormRow>
          <FormRow label="Şirket Giriş Tarihi"><DateInput value={form.sirketGiris} onChange={f("sirketGiris")} /></FormRow>
          <FormRow label="Durumu"><Select value={form.durum} onChange={f("durum")}>{["Çalışıyor","İzinde","Ayrıldı","Askıda"].map(d=><option key={d}>{d}</option>)}</Select></FormRow>
          <FormRow label="Devam Kontrolü">
            <Select value={form.devamKontrol} onChange={f("devamKontrol")}>
              <option>Yapılacak</option>
              <option>Yapılmayacak</option>
            </Select>
          </FormRow>
          {devamKontrolYapilmayacak && (
            <div style={{gridColumn:"1/-1",padding:12,background:"#E6F1FB",border:"1px solid #185FA5",borderRadius:8}}>
              <div style={{fontSize:12,color:"#185FA5",marginBottom:8}}>
                Bu personelin devam kontrolü yapılmayacak. Hareketleri otomatik olarak vardiyaya göre doldurulabilir.
              </div>
              <Btn onClick={autoFillHareketler} style={{fontSize:12}}>⚡ Hareketleri Vardiyaya Göre Doldur</Btn>
              {autoFillMsg && <div style={{marginTop:8,fontSize:12,color:"#3B6D11",fontWeight:500}}>{autoFillMsg}</div>}
            </div>
          )}
        </div>
      )}

      {tab==="maas" && (
        <div>
          {!alanGoster("personel_maas") ? (
            <div style={{padding:32,textAlign:"center",background:"var(--input-bg)",borderRadius:8,border:"1px solid var(--grid-line)"}}>
              <div style={{fontSize:32,marginBottom:12}}>🔒</div>
              <div style={{fontSize:14,color:"var(--text-secondary)"}}>Maaş bilgileri yetkinize göre gizlenmiştir.</div>
            </div>
          ) : (
          <div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12,marginBottom:16}}>
            <FormRow label="Net Ücret (₺)">
              <Input type="number" value={form.maas} onChange={f("maas")} placeholder="Net maaş giriniz" />
            </FormRow>
            <div style={{display:"flex",alignItems:"flex-end",paddingBottom:4}}>
              <span style={{fontSize:12,color:"var(--text-secondary)"}}>Net girince brüt otomatik hesaplanır</span>
            </div>
          </div>
          <div style={{background:"var(--input-bg)",borderRadius:8,padding:16}}>
            <div style={{fontSize:11,color:"var(--text-tertiary)",marginBottom:10,fontWeight:600}}>NET → BRÜT HESAPLAMA</div>
            {[
              ["Net Ücret (Girilen)", form.maas||0, false],
              ["Brüt Maaş (Hesaplanan)", brutMaas, false],
              ["SGK İşçi Payı (%14)", -sgk, true],
              ["İşsizlik Sigortası (%1)", -issizlik, true],
              ["Gelir Vergisi (%20)", -gelirV, true],
              ["Damga Vergisi (%0.759)", -damgaV, true],
            ].map(([l,v,neg])=>(
              <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:"1px solid var(--grid-line)",fontSize:13}}>
                <span style={{color:"var(--text-secondary)"}}>{l}</span>
                <span style={{color:neg?"#A32D2D":l.includes("Net")?"#3B6D11":"var(--text-primary)",fontWeight:l.includes("Net")||l.includes("Brüt")?600:400}}>
                  {neg?"-":""}{Math.abs(v).toLocaleString("tr-TR")} ₺
                </span>
              </div>
            ))}
            <div style={{display:"flex",justifyContent:"space-between",padding:"10px 0",fontSize:13,color:"var(--text-tertiary)"}}>
              <span>Net Kontrol (hesaplanan)</span>
              <span style={{fontWeight:600}}>{netKontrol.toLocaleString("tr-TR")} ₺</span>
            </div>
          </div>
          </div>
          )}
        </div>
      )}

      {tab==="izin" && (
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
          <FormRow label="Ücretsiz İzin Devri (UI)"><Input type="number" value={form.uiDevir} onChange={f("uiDevir")} /></FormRow>
          <FormRow label="Yıllık İzin Devri (YI)"><Input type="number" value={form.yiDevir} onChange={f("yiDevir")} /></FormRow>
        </div>
      )}

      {tab==="notlar" && (
        <FormRow label="Notlar / Performans Değerlendirme">
          <textarea value={form.notlar} onChange={e=>setForm(prev=>({...prev,notlar:e.target.value}))} rows={6} style={{width:"100%",padding:"8px 10px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",fontFamily:"var(--font-sans)",resize:"vertical"}} />
        </FormRow>
      )}
    </Modal>
  );
};

// ─── SHIFT ATAMA ─────────────────────────────────────────────────────────────
const getHaftaPazar = (isoDate) => {
  const d = new Date(isoDate);
  const day = d.getDay();
  const diff = day===0 ? 0 : 7-day;
  d.setDate(d.getDate()+diff);
  return d.toISOString().slice(0,10);
};

const ShiftAtama = ({personeller, kullanici}) => {
  const getHaftaPazartesi = (isoDate) => {
    const d = new Date(isoDate);
    const day = d.getDay();
    const diff = (day===0 ? -6 : 1-day);
    d.setDate(d.getDate()+diff);
    return d.toISOString().slice(0,10);
  };
  const getHaftaPazar = (isoDate) => {
    const d = new Date(isoDate);
    const day = d.getDay();
    const diff = day===0 ? 0 : 7-day; // o haftanın pazarı
    d.setDate(d.getDate()+diff);
    return d.toISOString().slice(0,10);
  };
  const addDays = (isoDate, n) => {
    const d = new Date(isoDate); d.setDate(d.getDate()+n); return d.toISOString().slice(0,10);
  };
  const isoToDisplay = (iso) => {
    const [y,m,g] = iso.split("-");
    const gunler = ["Paz","Pts","Sal","Çar","Per","Cum","Cmt"];
    const gun = new Date(iso).getDay();
    return `${g}.${m} ${gunler[gun]}`;
  };

  const [pendingHafta, setPendingHafta] = useState(() => getHaftaPazartesi(BUGUN_ISO));
  const [pendingBitis, setPendingBitis] = useState(() => getHaftaPazar(getHaftaPazartesi(BUGUN_ISO)));
  const basInputRef = React.useRef(null);
  const bitInputRef = React.useRef(null);
  React.useEffect(()=>{ if(basInputRef.current) basInputRef.current.value=pendingHafta; }, [pendingHafta]);
  React.useEffect(()=>{ if(bitInputRef.current) bitInputRef.current.value=pendingBitis; }, [pendingBitis]);
  const [oncekiHaftaYukle, setOncekiHaftaYukle] = useState(false);
  // Listeleme seçenekleri
  const [opt, setOpt] = useState({
    mesaiToplamGoster: false,
    saatAraligindaCalisanlar: false,
    izinBakiyeleriYukle: false,
    servisDurakBilgisi: false,
    imzaAlaniOlsun: false,
    ekAciklamalarYazdir: false,
    shiftToplamlariYazdir: false,
    herDeptAyriSayfa: false,
    calismaSaatleriYazdir: false,
  });
  const setO = (key) => (e) => setOpt(p=>({...p,[key]:e.target.checked}));
  const [showOpt, setShowOpt] = useState(false);
  const izinliDeptler = kullanici?.yetki==="admin"
    ? [...new Set([...getDepartmanlar().map(d=>d.ad), ...personeller.map(p=>p.departman).filter(Boolean)])].sort()
    : (kullanici?.departmanlar||[]);
  const [dept, setDept] = useState(() => izinliDeptler[0]||DEPARTMANLAR[0]);
  const [assignments, setAssignments] = useState(() => getShiftData());
  const [draft, setDraft] = useState({});
  const [selectedShift, setSelectedShift] = useState(null);
  const [selCells, setSelectedCells] = useState(new Set());
  const [dirty, setDirty] = useState(false);
  const isDragging = useRef(false);
  const dragStart = useRef(null);

  // Listele butonuna basınca haftayı güncelle
  const [haftaBaslangic, setHaftaBaslangic] = useState(() => getHaftaPazartesi(BUGUN_ISO));
  const [haftaBitis, setHaftaBitis] = useState(() => getHaftaPazar(getHaftaPazartesi(BUGUN_ISO)));

  const handleListele = () => {
    if(dirty && !confirm("Kaydedilmemiş değişiklikler var. Devam edilsin mi?")) return;
    setDraft({}); setDirty(false);
    if(oncekiHaftaYukle) {
      // Seçilen aralığın bir hafta öncesini hesapla
      const gunFarki = Math.round((new Date(pendingBitis) - new Date(pendingHafta)) / 86400000);
      const oncekiBas = addDays(pendingHafta, -(gunFarki+1));
      // pendingHafta → pendingBitis arası günler
      const hedefGunSayisi = gunFarki + 1;
      const hedefDays = Array.from({length:hedefGunSayisi},(_,i) => addDays(pendingHafta, i));
      const oncekiDays = Array.from({length:hedefGunSayisi},(_,i) => addDays(oncekiBas, i));
      const mevcutData = getShiftData();
      const kopyalar = {};
      personeller.filter(p=>izinliDeptler.includes(p.departman)).forEach(p => {
        hedefDays.forEach((iso, gi) => {
          const thisKey = `${p.id}-${iso}`;
          const prevKey = `${p.id}-${oncekiDays[gi]}`;
          if(!mevcutData[thisKey] && mevcutData[prevKey]) kopyalar[thisKey] = mevcutData[prevKey];
        });
      });
      if(Object.keys(kopyalar).length > 0) {
        const yeni = {...mevcutData, ...kopyalar};
        saveShiftData(yeni); setAssignments(yeni);
      }
    }
    setHaftaBaslangic(pendingHafta);
    setHaftaBitis(pendingBitis);
  };

  // weekDays: başlangıç → bitiş arası tüm günler (max 31)
  const weekDays = (() => {
    const days = [];
    let cur = haftaBaslangic;
    while(cur <= haftaBitis && days.length < 31) {
      days.push(cur);
      cur = addDays(cur, 1);
    }
    return days;
  })();

  // İşe giriş/çıkış tarihine göre filtrele — bu hafta içinde çalışmıyor olabilir
  const trToIso = (tr) => {
    if(!tr) return null;
    const [g,m,y] = tr.split(".");
    return `${y}-${m}-${g}`;
  };

  const filteredAll = React.useMemo(() =>
    personeller.filter(p => (kullanici?.yetki==="admin" || izinliDeptler.includes(p.departman)) && (dept==="TÜMÜ" ? true : p.departman===dept))
  , [personeller, dept, izinliDeptler, kullanici]);

  const filtered = React.useMemo(() => filteredAll.filter(p => {
    const isGirisIso = trToIso(p.isGiris);
    const istenCikisIso = trToIso(p.istenCikis);
    const hftBitis = addDays(haftaBaslangic, 6);
    if(isGirisIso && isGirisIso > hftBitis) return false;
    if(istenCikisIso && istenCikisIso < haftaBaslangic) return false;
    if(p.durum === "Ayrıldı" && istenCikisIso && istenCikisIso < haftaBaslangic) return false;
    return true;
  }), [filteredAll, haftaBaslangic]);
  const getShift = (pid, iso) => {
    const key = `${pid}-${iso}`;
    return draft[key] ?? assignments[key] ?? "";
  };

  const getCellsInRange = (start, end) => {
    if(!start||!end) return new Set();
    const minPi=Math.min(start.pi,end.pi), maxPi=Math.max(start.pi,end.pi);
    const minDi=Math.min(start.di,end.di), maxDi=Math.max(start.di,end.di);
    const cells = new Set();
    for(let pi=minPi;pi<=maxPi;pi++)
      for(let di=minDi;di<=maxDi;di++)
        if(filtered[pi]) cells.add(`${filtered[pi].id}-${weekDays[di]}`);
    return cells;
  };
  const handleMouseDown = (pi,di,e) => {
    e.preventDefault();
    isDragging.current = true;
    dragStart.current = {pi,di};
    // Her zaman sürükleme başlat — shift seçili olsun ya da olmasın
    setSelectedCells(getCellsInRange({pi,di},{pi,di}));
  };
  const handleMouseEnter = (pi,di) => {
    if(!isDragging.current) return;
    setSelectedCells(getCellsInRange(dragStart.current,{pi,di}));
  };
  const handleMouseUp = () => { isDragging.current=false; };
  // Tarih kontrolü: GG.MM.YYYY → ISO
  const trToIsoShift = (tr) => {
    if(!tr) return null;
    const parts = tr.split(".");
    if(parts.length!==3) return null;
    const [g,m,y] = parts;
    return `${y}-${m.padStart(2,"0")}-${g.padStart(2,"0")}`;
  };

  const isAdmin = kullanici?.yetki === "admin";
  const fp = getFirmaParams();
  const shiftGirmeYetkisi = isAdmin || fp.departmanPuantajYetkisi !== false;
  const izinGirmeYetkisi  = isAdmin || fp.departmanIzinGirisYetkisi !== false;
  const IZIN_KODLARI_SET  = new Set(IZINLER.map(i=>i.kod));

  const handleKeyDown = (e) => {
    if(e.key==="Enter" && selectedShift && selCells.size>0) {

      // Yetki kontrolü
      const secilenIzinMi = IZIN_KODLARI_SET.has(selectedShift);
      if(secilenIzinMi && !izinGirmeYetkisi) {
        alert("⚠️ İzin giriş yetkiniz yok."); setSelCells(new Set()); return;
      }
      if(!secilenIzinMi && selectedShift !== "OFF" && selectedShift !== "RT" && !shiftGirmeYetkisi) {
        alert("⚠️ Shift giriş yetkiniz yok."); setSelCells(new Set()); return;
      }

      // Kullanıcılar geçmişe shift/izin giremez — sadece bugün ve sonrası
      if(!isAdmin) {
        const gecmisTarihler = [...selCells].filter(k => k.slice(-10) < BUGUN_ISO);
        if(gecmisTarihler.length > 0) {
          alert("⚠️ Geçmiş tarihlere shift veya izin girişi yapamazsınız.\nSadece bugün ve sonraki günler için giriş yapabilirsiniz.");
          setSelCells(new Set()); return;
        }
      }

      // 11 saat kuralı kontrolü (vardiya ise)
      const fp2 = getFirmaParams();
      const onbirKural = fp2.onbirsaatOncesiShiftAtamaOnayi || "yok";
      if(onbirKural !== "yok" && !secilenIzinMi && selectedShift !== "OFF" && selectedShift !== "RT") {
        const mevcutData = {...assignments, ...draft};
        const ihlalEdenler = [];
        selCells.forEach(k => {
          const iso = k.slice(-10);
          const pid = k.slice(0, -11);
          const kontrol = onbirSaatKontrol(pid, iso, selectedShift, mevcutData);
          if(kontrol.ihlal) {
            const per = filtered.find(x=>String(x.id)===String(pid));
            ihlalEdenler.push({k, pid, iso, per, fark:kontrol.fark});
          }
        });

        if(ihlalEdenler.length > 0) {
          if(onbirKural === "engelle") {
            const mesaj = ihlalEdenler.map(x=>`${x.per?.ad||""} ${x.per?.soyad||""}: ${x.iso} — Dinlenme süresi ${Math.round(x.fark/60*10)/10} saat (min 11 saat)`).join("\n");
            alert(`⚠️ 11 Saat Kuralı İhlali — Shift girilemez!\n\n${mesaj}`);
            setSelCells(new Set()); return;
          }
          if(onbirKural === "onay") {
            // Onay bekleyene ekle, draft'a değil
            const mevcutOnay = getOnayBekleyen();
            const yeniOnaylar = ihlalEdenler.map(x=>({
              id: `${x.pid}-${x.iso}-${Date.now()}`,
              pid: x.pid, iso: x.iso, kod: selectedShift,
              tip: "11saat", tarih: new Date().toLocaleDateString("tr-TR"),
              personelAd: `${x.per?.ad||""} ${x.per?.soyad||""}`, durum:"bekliyor"
            }));
            saveOnayBekleyen([...mevcutOnay, ...yeniOnaylar]);
            // Onaya giden hücreleri draft'tan çıkar
            const normalCells = new Set([...selCells].filter(k=>!ihlalEdenler.find(x=>x.k===k)));
            if(normalCells.size > 0) {
              const u={}; normalCells.forEach(k=>{u[k]=selectedShift;});
              setDraft(p=>({...p,...u})); setDirty(true);
            }
            alert(`⚠️ ${ihlalEdenler.length} atama 11 saat kuralı nedeniyle onaya gönderildi. Kalan ${normalCells.size} atama kaydedildi.`);
            setSelCells(new Set()); return;
          }
        }
      }

      // İzin onay — kim girerse girsin onay listesine düşür
      if(secilenIzinMi) {
        const mevcutOnay = getOnayBekleyen();
        const yeniOnaylar = [...selCells].map(k=>{
          const iso=k.slice(-10); const pid=k.slice(0,-11);
          const per=filtered.find(x=>String(x.id)===String(pid));
          return {
            id:`${pid}-${iso}-izin-${Date.now()}`,
            pid, iso, kod:selectedShift, tip:"izin",
            tarih:new Date().toLocaleDateString("tr-TR"),
            personelAd:`${per?.ad||""} ${per?.soyad||""}`,
            girenAd: kullanici?.ad ? `${kullanici.ad} ${kullanici.soyad||""}` : (kullanici?.yetki==="admin"?"Admin":""),
            durum:"bekliyor"
          };
        });
        saveOnayBekleyen([...mevcutOnay, ...yeniOnaylar]);
        // Shift data'ya da hemen yaz — görünür olsun, onay ayrıca takip edilsin
        const sd = getShiftData();
        [...selCells].forEach(k=>{
          const iso=k.slice(-10); const pid=k.slice(0,-11);
          sd[`${pid}-${iso}`] = selectedShift;
        });
        saveShiftData(sd);
        setDraft(p=>({...p,...Object.fromEntries([...selCells].map(k=>[k,selectedShift]))}));
        setDirty(true);
        setSelCells(new Set()); return;
      }
      const tarihHatalar = [];
      selCells.forEach(k => {
        const iso = k.slice(-10);
        const pid = k.slice(0, -11);
        const per = filtered.find(x => String(x.id) === String(pid));
        if(!per) return;
        const girisIso = trToIsoShift(per.isGiris);
        const cikisIso = trToIsoShift(per.istenCikis);
        if(girisIso && iso < girisIso) {
          tarihHatalar.push(`${per.ad} ${per.soyad}: ${iso} tarihi işe giriş (${per.isGiris}) öncesi`);
        }
        if(cikisIso && iso > cikisIso) {
          tarihHatalar.push(`${per.ad} ${per.soyad}: ${iso} tarihi işten çıkış (${per.istenCikis}) sonrası`);
        }
      });
      if(tarihHatalar.length > 0) {
        const uniq = [...new Set(tarihHatalar)];
        alert(`⚠️ Tarih Hatası\n\nAşağıdaki günler için shift girilemez:\n\n${uniq.slice(0,8).join("\n")}`);
        setSelCells(new Set());
        return;
      }

      if(selectedShift==="OFF") {
        // Her personel için OFF sayısını kontrol et — haftada tam 1 OFF
        const uyarilar = [];
        // Hangi personeller etkileniyor ve kaç gün seçili
        const etkilenenler = {};
        selCells.forEach(k => {
          const iso = k.slice(-10);
          const pid = k.slice(0, -11);
          if(!etkilenenler[pid]) etkilenenler[pid] = [];
          etkilenenler[pid].push(iso);
        });

        Object.entries(etkilenenler).forEach(([pid, gunler]) => {
          // Zaten bu haftada mevcut OFF var mı? (seçilenler dışında)
          const mevcutOffVar = weekDays.some(iso =>
            !gunler.includes(iso) &&
            (draft[`${pid}-${iso}`] ?? assignments[`${pid}-${iso}`]) === "OFF"
          );
          // Seçilen günlerde birden fazla OFF mu?
          if(gunler.length > 1) {
            const per = filtered.find(x => String(x.id) === String(pid));
            uyarilar.push(`${per ? per.ad+" "+per.soyad : pid}: Aynı anda ${gunler.length} gün seçtiniz, haftada sadece 1 OFF girilebilir.`);
          } else if(mevcutOffVar) {
            const per = filtered.find(x => String(x.id) === String(pid));
            uyarilar.push(`${per ? per.ad+" "+per.soyad : pid}: Bu hafta zaten 1 OFF girilmiş. Haftada sadece 1 OFF kullanılabilir.`);
          }
        });

        if(uyarilar.length > 0) {
          alert(`⚠️ OFF Kuralı\n\nHaftada tam 1 OFF girilmelidir:\n\n${uyarilar.join("\n")}`);
          setSelCells(new Set());
          return;
        }
      }

      const u={};
      selCells.forEach(k => { u[k] = selectedShift; });
      setDraft(p=>({...p,...u}));
      setDirty(true);
      setSelCells(new Set());
    }
    if(e.key==="Escape") { setSelCells(new Set()); setSelectedShift(null); }
    if((e.key==="Delete" || e.key==="Backspace") && selCells.size>0) {
      if(!shiftGirmeYetkisi && !izinGirmeYetkisi) {
        alert("⚠️ Silme yetkiniz yok."); setSelCells(new Set()); return;
      }
      const u={};
      selCells.forEach(k => { u[k] = ""; });
      setDraft(p => {
        const next = {...p};
        Object.keys(u).forEach(k => { delete next[k]; });
        return next;
      });
      // assignments'tan da sil
      setAssignments(prev => {
        const next = {...prev};
        Object.keys(u).forEach(k => { delete next[k]; });
        return next;
      });
      setDirty(true);
      setSelCells(new Set());
    }
  };

  const kaydet = () => {
    const bosList = [];
    const offEksikList = [];
    filtered.forEach(p => {
      const girisIso = trToIsoShift(p.isGiris);
      const cikisIso = trToIsoShift(p.istenCikis);

      // Pasif olmayan günler (kişi o gün aktif çalışıyor olmalı)
      const aktifGunler = weekDays.filter(iso => {
        if(girisIso && iso < girisIso) return false; // işe girmemiş
        if(cikisIso && iso > cikisIso) return false; // işten ayrılmış
        return true;
      });

      // Boş hücre kontrolü — sadece aktif günlerde
      const bosGunler = aktifGunler.filter(iso => {
        const s = draft[`${p.id}-${iso}`] ?? assignments[`${p.id}-${iso}`];
        return !s;
      });
      bosGunler.forEach(iso => {
        const [y,m,g] = iso.split("-");
        bosList.push(`${p.ad} ${p.soyad} — ${g}.${m}.${y}`);
      });

      // OFF kontrolü — sadece aktif günlerde
      const offSayisi = aktifGunler.filter(iso =>
        (draft[`${p.id}-${iso}`] ?? assignments[`${p.id}-${iso}`]) === "OFF"
      ).length;
      // Aktif gün yoksa OFF kontrolü yapma
      if(aktifGunler.length === 0) return;
      if(offSayisi === 0) offEksikList.push(`${p.ad} ${p.soyad}`);
      if(offSayisi > 1)   offEksikList.push(`${p.ad} ${p.soyad}: ${offSayisi} OFF var (max 1)`);
    });

    let mesaj = "";
    if(offEksikList.length > 0) {
      mesaj += `⚠️ OFF Sorunu (${offEksikList.length} kişi):\n${offEksikList.slice(0,8).join("\n")}${offEksikList.length>8?"\n...":""}\n\n`;
    }
    if(bosList.length > 0) {
      mesaj += `📋 Shift girilmemiş (${bosList.length} gün):\n${bosList.slice(0,8).join("\n")}${bosList.length>8?"\n...":""}`;
    }
    if(mesaj) {
      if(!confirm(mesaj + "\n\nYine de kaydetmek istiyor musunuz?")) return;
    }

    const yeni = {...assignments, ...draft};
    setAssignments(yeni);
    saveShiftData(yeni);
    setDraft({}); setDirty(false);
    alert("✓ Shift atamaları kaydedildi.");
  };
  const vazgec = () => { if(dirty && !confirm("Kaydedilmemis degisiklikler var. Vazgecmek istiyor musunuz?")) return; setDraft({}); setDirty(false); setSelCells(new Set()); setSelectedShift(null); };
  const haftaDegistir = (yon) => { if(dirty && !confirm("Kaydedilmemis degisiklikler var. Devam edilsin mi?")) return; setDraft({}); setDirty(false); setHaftaBaslangic(p => addDays(p, yon*7)); };
  // Draft + assignments birleştir (draft öncelikli) — aynı key iki kez sayılmaz
  const mergedData = React.useMemo(()=>({...assignments, ...draft}), [assignments, draft]);
  const getShiftMerged = (pid, iso) => mergedData[`${pid}-${iso}`] ?? "";
  const counts = React.useMemo(() => weekDays.map(iso => {
    const c={};
    filtered.forEach(p=>{
      const s = mergedData[`${p.id}-${iso}`] ?? "";
      if(s) c[s]=(c[s]||0)+1;
    });
    return c;
  }), [weekDays, filtered, mergedData]);
  const inputDateStyle = {padding:"7px 10px",border:"1.5px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",colorScheme:"dark"};
  // Kullanımda olanları sıra numarasına göre sırala
  const currentShifts = [...SHIFTS]
    .filter(s => s.kullanimda !== false)
    .sort((a,b) => (a.siraNo||99) - (b.siraNo||99));

  return (
    <div onKeyDown={handleKeyDown} onMouseUp={handleMouseUp} tabIndex={0} style={{outline:"none"}} ref={el=>el&&el.focus()}>
      {/* Kontrol barı */}
      <div style={{display:"flex",gap:6,marginBottom:8,alignItems:"center",justifyContent:"space-between"}}>
        {/* Sol grup */}
        <div style={{display:"flex",gap:6,alignItems:"center",flexWrap:"nowrap",overflow:"hidden"}}>
          <Select value={dept} onChange={e=>setDept(e.target.value)} style={{width:180,flexShrink:0}}>
            {izinliDeptler.length>1 && <option value="TÜMÜ">Tüm Departmanlar</option>}
            {izinliDeptler.map(d=><option key={d}>{d}</option>)}
          </Select>
          <input ref={basInputRef} type="date" defaultValue={pendingHafta}
            onBlur={e=>{ if(e.target.value?.length===10){const v=e.target.value; setPendingHafta(v); setPendingBitis(getHaftaPazar(v));} }}
            onChange={e=>{ if(e.target.value?.length===10){const v=e.target.value; setPendingHafta(v); setPendingBitis(getHaftaPazar(v));} }}
            style={inputDateStyle} />
          <span style={{fontSize:12,color:"var(--text-secondary)"}}>—</span>
          <input ref={bitInputRef} type="date" defaultValue={pendingBitis}
            onBlur={e=>{ if(e.target.value?.length===10) setPendingBitis(e.target.value); }}
            onChange={e=>{ if(e.target.value?.length===10) setPendingBitis(e.target.value); }}
            style={inputDateStyle} />
          <Btn onClick={()=>{const y=getHaftaPazartesi(addDays(pendingHafta,-7));setPendingHafta(y);setPendingBitis(getHaftaPazar(y));}} title="Önceki hafta">◀</Btn>
          <Btn onClick={()=>{const y=getHaftaPazartesi(addDays(pendingHafta,7));setPendingHafta(y);setPendingBitis(getHaftaPazar(y));}} title="Sonraki hafta">▶</Btn>
          <Btn primary onClick={handleListele}><span style={{fontSize:16}}>📋</span><span>Listele</span></Btn>
        <Btn onClick={()=>{
          const sirketAd = getFirmaParams().sirketUnvani || "TimeCore";
          const deptAd = dept==="TÜMÜ" ? "Tüm Departmanlar" : dept;
          const gunLabels = weekDays.map(iso=>{
            const d=new Date(iso); const [y,m,g]=iso.split("-");
            const gunler=["Paz","Pts","Sal","Çar","Per","Cum","Cmt"];
            const s = opt.calismaSaatleriYazdir
              ? (() => { // En çok kullanılan shift bu günde
                  const kodlar = filtered.map(p=>getShift(p.id,iso)).filter(Boolean);
                  const enCok = kodlar.length ? kodlar.sort((a,b)=>kodlar.filter(x=>x===b).length-kodlar.filter(x=>x===a).length)[0] : null;
                  const sObj = enCok ? SHIFTS.find(x=>x.kod===enCok) : null;
                  return sObj?.giris ? `${sObj.giris}-${sObj.cikis}` : "";
                })() : "";
            return {iso, label:`${g}.${m}`, gun:gunler[d.getDay()], saat:s};
          });

          // Departman listesi — "Her Departman Ayrı Sayfada" için
          const deptListesi = opt.herDeptAyriSayfa && dept==="TÜMÜ"
            ? [...new Set(filtered.map(p=>p.departman))]
            : [dept==="TÜMÜ" ? null : dept];

          const buildTableHTML = (kisiler, deptBaslik) => {
            const satirlar = kisiler.map((p,i)=>{
              const hucre = weekDays.map(iso=>{
                const kod = getShift(p.id,iso)||"—";
                const girisIso = p.isGiris?p.isGiris.split(".").reverse().join("-"):null;
                const cikisIso = p.istenCikis?p.istenCikis.split(".").reverse().join("-"):null;
                if(girisIso&&iso<girisIso) return `<td style='background:#f0f0f0;color:#aaa;text-align:center'>—</td>`;
                if(cikisIso&&iso>cikisIso) return `<td style='background:#ffe0e0;color:#aaa;text-align:center'>—</td>`;
                const sObj=[...SHIFTS,...IZINLER].find(x=>x.kod===kod);
                // Çalışma saatleri göster seçiliyse shift kodu yerine saat
                const goruntu = opt.calismaSaatleriYazdir && sObj?.giris ? `${sObj.giris}-${sObj.cikis}` : kod;
                return `<td style='text-align:center;font-weight:700;font-size:${opt.calismaSaatleriYazdir?"9px":"11px"};${sObj?`background:${sObj.bg};color:${sObj.renk}`:""}'>${goruntu}</td>`;
              }).join("");
              const imza = opt.imzaAlaniOlsun ? `<td>&nbsp;</td>` : "";
              return `<tr><td style='text-align:center'>${i+1}</td><td style='font-weight:600;white-space:nowrap'>${p.ad} ${p.soyad}</td><td style='font-size:10px'>${p.gorev||""}</td>${hucre}${imza}</tr>`;
            }).join("");

            // Shift toplamları — resim gibi detaylı tablo
            let toplamHTML = "";
            if(opt.shiftToplamlariYazdir) {
              const tumKodlar = [...siralanmisShifts(SHIFTS).map(s=>s.kod), ...IZINLER.map(s=>s.kod)];
              const kullanilan = tumKodlar.filter(kod => kisiler.some(p=>weekDays.some(iso=>getShift(p.id,iso)===kod)));
              const toplamSatirlari = kullanilan.map(kod=>{
                const sObj=[...SHIFTS,...IZINLER].find(x=>x.kod===kod);
                const gunToplam = weekDays.map(iso=>kisiler.filter(p=>getShift(p.id,iso)===kod).length);
                const genelTop = gunToplam.reduce((a,b)=>a+b,0);
                return `<tr style='${sObj?`background:${sObj.bg};color:${sObj.renk}`:""}'>
                  <td colspan='2' style='font-weight:700;padding:3px 6px;border:1px solid #ccc'>${kod}${sObj&&sObj.giris?` (${sObj.giris}-${sObj.cikis})`:sObj?.ad?` - ${sObj.ad}`:""}</td>
                  ${gunToplam.map(n=>`<td style='text-align:center;border:1px solid #ccc;font-weight:600'>${n||""}</td>`).join("")}
                  <td style='text-align:center;border:1px solid #ccc;font-weight:700'>${genelTop||""}</td>
                </tr>`;
              });
              // İzin toplamı, aktif toplamı, toplam personel satırları
              const izinKodlari = new Set(IZINLER.map(s=>s.kod));
              const aktifKodlari = new Set(SHIFTS.filter(s=>s.giris).map(s=>s.kod));
              const toplamIzin = weekDays.map(iso=>kisiler.filter(p=>izinKodlari.has(getShift(p.id,iso))).length);
              const toplamAktif = weekDays.map(iso=>kisiler.filter(p=>aktifKodlari.has(getShift(p.id,iso))).length);
              const toplamPersonel = weekDays.map(()=>kisiler.length);

              toplamHTML = `<table style='width:100%;border-collapse:collapse;margin-top:8px;font-size:11px'>
                <thead><tr style='background:#e8e8e8'>
                  <th colspan='2' style='padding:4px 6px;border:1px solid #ccc;text-align:left'>Vardiya / İzin</th>
                  ${weekDays.map((_,i)=>`<th style='border:1px solid #ccc;text-align:center'>${gunLabels[i].label}<br/><small>${gunLabels[i].gun}</small></th>`).join("")}
                  <th style='border:1px solid #ccc'>Toplam</th>
                </tr></thead>
                <tbody>
                  ${toplamSatirlari.join("")}
                  <tr style='font-weight:700;background:#fff3cd'>
                    <td colspan='2' style='padding:3px 6px;border:1px solid #ccc'>Toplam İzin</td>
                    ${toplamIzin.map(n=>`<td style='text-align:center;border:1px solid #ccc'>${n||""}</td>`).join("")}
                    <td style='text-align:center;border:1px solid #ccc'>${toplamIzin.reduce((a,b)=>a+b,0)||""}</td>
                  </tr>
                  <tr style='font-weight:700;background:#d4edda'>
                    <td colspan='2' style='padding:3px 6px;border:1px solid #ccc'>Toplam Aktif</td>
                    ${toplamAktif.map(n=>`<td style='text-align:center;border:1px solid #ccc'>${n||""}</td>`).join("")}
                    <td style='text-align:center;border:1px solid #ccc'>${toplamAktif.reduce((a,b)=>a+b,0)||""}</td>
                  </tr>
                  <tr style='font-weight:700;background:#cce5ff'>
                    <td colspan='2' style='padding:3px 6px;border:1px solid #ccc'>Toplam Personel</td>
                    ${toplamPersonel.map(n=>`<td style='text-align:center;border:1px solid #ccc'>${n}</td>`).join("")}
                    <td style='text-align:center;border:1px solid #ccc'>${kisiler.length}</td>
                  </tr>
                </tbody>
              </table>`;
            }

            const imzaBaslik = opt.imzaAlaniOlsun ? "<th style='width:70px'>İmza</th>" : "";
            const imzaBolum = opt.imzaAlaniOlsun ? `<div style='display:flex;gap:80px;margin-top:40px'><div style='text-align:center'><div style='border-top:1px solid #333;width:160px;padding-top:4px;font-size:11px'>Departman Müdürü İmza</div></div><div style='text-align:center'><div style='border-top:1px solid #333;width:160px;padding-top:4px;font-size:11px'>Departman Şefi İmza</div></div></div>` : "";

            return `
              <div class='dt'>${new Date().toLocaleString("tr-TR")}</div>
              <h2>Haftalık Çalışma Planı</h2>
              <div class='sub'>${deptBaslik} - ${haftaBaslangic} / ${addDays(haftaBaslangic,6)}</div>
              <table>
                <thead><tr>
                  <th style='width:28px'>No</th><th>Personel</th><th>Pozisyon</th>
                  ${gunLabels.map(g=>`<th>${g.label}<br/><small>${g.gun}</small>${g.saat?`<br/><small style='font-size:8px'>${g.saat}</small>`:""}</th>`).join("")}
                  ${imzaBaslik}
                </tr></thead>
                <tbody>${satirlar}</tbody>
              </table>
              ${toplamHTML}
              ${imzaBolum}`;
          };

          // Sayfa(lar) oluştur
          const sayfalar = deptListesi.map(d=>{
            const kisiler = d ? filtered.filter(p=>p.departman===d) : filtered;
            return buildTableHTML(kisiler, d||"Tüm Departmanlar");
          });

          const html = `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Haftalık Çalışma Planı</title>
          <style>
            body{font-family:Arial,sans-serif;font-size:12px;margin:15px;color:#000}
            h2{text-align:center;margin:4px 0;font-size:15px}
            .sub{font-weight:bold;font-size:12px;margin-bottom:8px}
            .dt{text-align:right;font-size:10px;color:#666;margin-bottom:4px}
            table{width:100%;border-collapse:collapse}
            th,td{border:1px solid #ccc;padding:4px 5px;font-size:11px}
            th{background:#e8e8e8;text-align:center}
            .pg{page-break-after:always}
            @media print{@page{size:A4 landscape;margin:8mm}.pg{page-break-after:always}}
          </style></head><body>
          ${sayfalar.map((s,i)=>`<div class='${i<sayfalar.length-1?"pg":""}'>${s}</div>`).join("")}
          </body></html>`;

          const w=window.open("","_blank","width=1100,height=750");
          w.document.write(html); w.document.close(); w.focus();
          setTimeout(()=>w.print(),700);
        }}><span style={{fontSize:16}}>🖨️</span><span>Yazdır</span></Btn>
        <Btn onClick={async ()=>{
          // Excel — aynı yazdırma verisi
          const XLSX = await loadSheetJS();
          const wb = XLSX.utils.book_new();
          const gunLabelsXL = weekDays.map(iso=>{
            const d=new Date(iso); const [y,m,g]=iso.split("-");
            const gunler=["Paz","Pts","Sal","Çar","Per","Cum","Cmt"];
            const sObj = opt.calismaSaatleriYazdir ? (()=>{
              const kodlar=filtered.map(p=>getShift(p.id,iso)).filter(Boolean);
              const enCok=kodlar.length?kodlar.sort((a,b)=>kodlar.filter(x=>x===b).length-kodlar.filter(x=>x===a).length)[0]:null;
              const s=enCok?SHIFTS.find(x=>x.kod===enCok):null;
              return s?.giris?`${s.giris}-${s.cikis}`:"";
            })() : "";
            return `${g}.${m} ${gunler[d.getDay()]}${sObj?" "+sObj:""}`;
          });

          const deptListesiXL = opt.herDeptAyriSayfa && dept==="TÜMÜ"
            ? [...new Set(filtered.map(p=>p.departman))]
            : [dept==="TÜMÜ" ? null : dept];

          deptListesiXL.forEach(d => {
            const kisiler = d ? filtered.filter(p=>p.departman===d) : filtered;
            const baslik = d || "Tüm Departmanlar";
            const rows = [
              ["No","Personel","Pozisyon",...gunLabelsXL],
              ...kisiler.map((p,i)=>[
                i+1, `${p.ad} ${p.soyad}`, p.gorev||"",
                ...weekDays.map(iso=>{
                  const kod=getShift(p.id,iso)||"";
                  const girisIso=p.isGiris?p.isGiris.split(".").reverse().join("-"):null;
                  const cikisIso=p.istenCikis?p.istenCikis.split(".").reverse().join("-"):null;
                  if(girisIso&&iso<girisIso) return "-";
                  if(cikisIso&&iso>cikisIso) return "-";
                  if(opt.calismaSaatleriYazdir){const s=SHIFTS.find(x=>x.kod===kod);return s?.giris?`${s.giris}-${s.cikis}`:kod;}
                  return kod;
                })
              ])
            ];

            // Toplam tablosu
            if(opt.shiftToplamlariYazdir) {
              rows.push([]);
              rows.push(["Vardiya","Toplam",...gunLabelsXL]);
              const tumKodlar=[...siralanmisShifts(SHIFTS).map(s=>s.kod),...IZINLER.map(s=>s.kod)];
              const kullanilan=tumKodlar.filter(kod=>kisiler.some(p=>weekDays.some(iso=>getShift(p.id,iso)===kod)));
              kullanilan.forEach(kod=>{
                const gunToplam=weekDays.map(iso=>kisiler.filter(p=>getShift(p.id,iso)===kod).length);
                rows.push([kod,gunToplam.reduce((a,b)=>a+b,0),...gunToplam]);
              });
              const izinKod=new Set(IZINLER.map(s=>s.kod));
              const aktifKod=new Set(SHIFTS.filter(s=>s.giris).map(s=>s.kod));
              const ti=weekDays.map(iso=>kisiler.filter(p=>izinKod.has(getShift(p.id,iso))).length);
              const ta=weekDays.map(iso=>kisiler.filter(p=>aktifKod.has(getShift(p.id,iso))).length);
              rows.push(["Toplam İzin",ti.reduce((a,b)=>a+b,0),...ti]);
              rows.push(["Toplam Aktif",ta.reduce((a,b)=>a+b,0),...ta]);
              rows.push(["Toplam Personel",kisiler.length,...weekDays.map(()=>kisiler.length)]);
            }

            const ws = XLSX.utils.aoa_to_sheet(rows);
            ws["!cols"] = [6,22,18,...weekDays.map(()=>12)].map(wch=>({wch}));
            // Başlık satırı kalın
            const range = XLSX.utils.decode_range(ws["!ref"]);
            for(let c=range.s.c;c<=range.e.c;c++){
              const cell=ws[XLSX.utils.encode_cell({r:0,c})];
              if(cell) cell.s={font:{bold:true},fill:{fgColor:{rgb:"C5D9F1"}}};
            }
            const sheetAd = baslik.substring(0,31);
            XLSX.utils.book_append_sheet(wb, ws, sheetAd);
          });

          const tarih = new Date().toLocaleDateString("tr-TR").replace(/\./g,"-");
          XLSX.writeFile(wb, `Haftalık_Çalışma_Planı_${tarih}.xlsx`);
        }}><span style={{fontSize:16}}>📥</span><span>Excel</span></Btn>
        </div>
        {/* Sağ grup — her zaman sağda */}
        <div style={{display:"flex",gap:6,alignItems:"center",flexShrink:0}}>
          {dirty && <Btn danger onClick={vazgec}>Vazgeç</Btn>}
          <Btn primary onClick={kaydet} style={{fontWeight:700}}><span style={{fontSize:16}}>💾</span><span>Kaydet [F2]</span></Btn>
        </div>
      </div>
      {/* Önceki haftayı yükle */}
      {/* Seçenekler — kompakt accordion */}
      <div style={{marginBottom:8,border:"1px solid var(--grid-line)",borderRadius:6,overflow:"hidden"}}>
        <div onClick={()=>setShowOpt(v=>!v)}
          style={{display:"flex",alignItems:"center",gap:8,padding:"6px 12px",background:"var(--input-bg)",cursor:"pointer",userSelect:"none"}}>
          <span style={{fontSize:12,fontWeight:500,color:"var(--text-secondary)"}}>⚙️ Seçenekler</span>
          {/* Aktif seçenek sayısı */}
          {Object.values(opt).filter(Boolean).length > 0 &&
            <span style={{background:"#185FA5",color:"#fff",borderRadius:20,padding:"0px 7px",fontSize:10,fontWeight:700}}>
              {Object.values(opt).filter(Boolean).length}
            </span>
          }
          <span style={{marginLeft:"auto",fontSize:11,color:"var(--text-tertiary)"}}>{showOpt?"▲":"▼"}</span>
        </div>
        {showOpt && (
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",background:"var(--card-bg)"}}>
            <div style={{padding:"10px 14px",borderRight:"1px solid var(--grid-line)"}}>
              <div style={{fontSize:9,fontWeight:700,color:"var(--text-tertiary)",marginBottom:6,letterSpacing:.05}}>LİSTELEME</div>
              {[
                ["mesaiToplamGoster",        "Mesai Toplamlarını Göster"],
                ["saatAraligindaCalisanlar", "Saat Aralığında Çalışanlar"],
                ["izinBakiyeleriYukle",      "İzin Bakiyeleri Yüklensin"],
                ["servisDurakBilgisi",       "Servis - Durak Bilgisi"],
                ["oncekiHafta",              "Önceki Hafta Verisiyle Yükle"],
              ].map(([key,label])=>(
                <label key={key} style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer",fontSize:11,color:"var(--text-secondary)",marginBottom:3}}>
                  <input type="checkbox"
                    checked={key==="oncekiHafta"?oncekiHaftaYukle:(opt[key]||false)}
                    onChange={key==="oncekiHafta"?e=>setOncekiHaftaYukle(e.target.checked):setO(key)} />
                  {label}
                </label>
              ))}
            </div>
            <div style={{padding:"10px 14px"}}>
              <div style={{fontSize:9,fontWeight:700,color:"var(--text-tertiary)",marginBottom:6,letterSpacing:.05}}>YAZDIRMA</div>
              {[
                ["imzaAlaniOlsun",        "İmza Alanı Olsun"],
                ["ekAciklamalarYazdir",   "Ek Açıklamalar Yazdırılsın"],
                ["shiftToplamlariYazdir", "Shift Toplamları Yazdırılsın"],
                ["herDeptAyriSayfa",      "Her Departman Ayrı Sayfa"],
                ["calismaSaatleriYazdir", "Çalışma Saatleri Yazdırılsın"],
              ].map(([key,label])=>(
                <label key={key} style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer",fontSize:11,color:"var(--text-secondary)",marginBottom:3}}>
                  <input type="checkbox" checked={opt[key]||false} onChange={setO(key)} />
                  {label}
                </label>
              ))}
            </div>
          </div>
        )}
      </div>
      {dirty && <div style={{marginBottom:8,padding:"6px 12px",background:"#FAEEDA",border:"1px solid #854F0B",borderRadius:6,fontSize:12,color:"#854F0B"}}>⚠️ Kaydedilmemiş değişiklikler var — kaydetmeden çıkmak istediğinizde uyarı alırsınız.</div>}
      <div style={{marginBottom:4,display:"flex",gap:3,flexWrap:"wrap",alignItems:"center",padding:"5px 8px",background:"var(--input-bg)",borderRadius:6,border:"1px solid var(--grid-line)"}}>
        {/* Vardiyalar */}
        {shiftGirmeYetkisi
          ? currentShifts.map(s=>{
              const sel=selectedShift===s.kod;
              return <span key={s.kod} onClick={()=>setSelectedShift(sel?null:s.kod)}
                title={s.ad+(s.giris?` (${s.giris}-${s.cikis})`:"")}
                style={{background:sel?"#1e40af":(s.bg||"#F1EFE8"),color:sel?"#fff":"#000",
                  padding:"3px 8px",borderRadius:5,fontSize:11,fontWeight:700,
                  cursor:"pointer",border:sel?"2px solid #60a5fa":"1px solid rgba(0,0,0,0.08)",
                  userSelect:"none",whiteSpace:"nowrap",minWidth:32,textAlign:"center"}}>
                {sel&&s.giris ? `${s.kod} ${s.giris}-${s.cikis}` : s.kod}
              </span>;
            })
          : <span style={{fontSize:11,color:"var(--text-tertiary)",fontStyle:"italic"}}>Shift yetki yok</span>
        }
        {/* Ayraç */}
        <span style={{width:1,height:16,background:"var(--grid-line)",margin:"0 3px",flexShrink:0}} />
        {/* İzinler */}
        {izinGirmeYetkisi
          ? IZINLER.map(s=>{
              const sel=selectedShift===s.kod;
              return <span key={s.kod} onClick={()=>setSelectedShift(sel?null:s.kod)}
                title={s.ad}
                style={{background:sel?"#1e3a8a":s.bg,color:sel?"#fff":s.renk,
                  padding:"3px 8px",borderRadius:5,fontSize:11,fontWeight:600,
                  cursor:"pointer",border:sel?"2px solid #60a5fa":"1px solid rgba(0,0,0,0.06)",
                  userSelect:"none",whiteSpace:"nowrap"}}>
                {sel ? s.ad : s.kod}
              </span>;
            })
          : <span style={{fontSize:11,color:"var(--text-tertiary)",fontStyle:"italic"}}>İzin yetki yok</span>
        }
      </div>
      {selectedShift ? <div style={{marginBottom:8,padding:"6px 12px",background:"#EFF6FF",border:"1px solid #93c5fd",borderRadius:6,fontSize:12,color:"#1e40af",display:"flex",gap:10,alignItems:"center"}}><span style={{fontWeight:700}}>{selectedShift}</span><span>seçili — sürükle ve seç →</span><kbd style={{background:"#1e40af",color:"#fff",padding:"1px 7px",borderRadius:4,fontSize:11,fontWeight:600}}>Enter</kbd><span>ile uygula</span>{selCells.size>0 && <span style={{fontWeight:700,background:"#1e40af",color:"#fff",padding:"2px 8px",borderRadius:12,fontSize:11}}>{selCells.size} hücre</span>}<span style={{marginLeft:"auto",cursor:"pointer",opacity:.6}} onClick={()=>{setSelectedShift(null);setSelCells(new Set());}}>✕</span></div>
        : <div style={{marginBottom:8,padding:"6px 12px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:6,fontSize:12,color:"var(--text-secondary)",display:"flex",gap:16,alignItems:"center"}}>
          <span>Üstten shift seç → sürükle → <kbd style={{background:"var(--text-secondary)",color:"var(--card-bg)",padding:"1px 5px",borderRadius:3,fontSize:11}}>Enter</kbd> ile uygula</span>
          <span style={{color:"var(--text-tertiary)"}}>·</span>
          <span>Hücreye tıkla → seç → <kbd style={{background:"var(--text-secondary)",color:"var(--card-bg)",padding:"1px 5px",borderRadius:3,fontSize:11}}>Delete</kbd> ile sil</span>
          {selCells.size>0 && <span style={{fontWeight:700,background:"#1e40af",color:"#fff",padding:"2px 8px",borderRadius:12,fontSize:11,marginLeft:"auto"}}>{selCells.size} hücre seçili</span>}
        </div>}
      <div style={{overflowX:"auto",userSelect:"none"}}>
        {/* Departman başlığı */}
        <div style={{padding:"6px 10px",background:"var(--th-bg)",color:"#fff",fontWeight:700,fontSize:12,borderRadius:"6px 6px 0 0"}}>
          {dept==="TÜMÜ" ? "Tüm Departmanlar" : dept} — {haftaBaslangic} / {addDays(haftaBaslangic,6)}
        </div>
        <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:11}}>
          <thead><tr>
            <th style={{textAlign:"left",minWidth:100,maxWidth:120,padding:"5px 6px",fontSize:10}}>ADI</th>
            <th style={{textAlign:"left",minWidth:80,maxWidth:100,padding:"5px 6px",fontSize:10}}>SOYADI</th>
            <th style={{textAlign:"left",minWidth:90,maxWidth:110,padding:"5px 6px",fontSize:10}}>GÖREV</th>
            <th style={{textAlign:"left",minWidth:80,maxWidth:100,padding:"5px 6px",fontSize:10}}>DEPARTMAN</th>
            <th style={{padding:"5px 4px",fontSize:10,textAlign:"center",minWidth:28}}>YI</th>
            {weekDays.map(iso=>{
              return (
                <th key={iso} style={{padding:"4px 2px",fontSize:10,textAlign:"center",minWidth:52,background:iso===BUGUN_ISO?"rgba(255,255,255,0.15)":undefined}}>
                  {isoToDisplay(iso)}
                </th>
              );
            })}
            {opt.mesaiToplamGoster && <th style={{padding:"4px 2px",fontSize:10,textAlign:"center",minWidth:50,color:"#185FA5"}}>Mesai</th>}
          </tr></thead>
          <tbody>
            {(() => {
              const onaylar = getOnayBekleyen(); // bir kez oku, hücre döngüsünde değil
              return filtered.map((p,pi)=>{
              const girisIso = trToIsoShift(p.isGiris);
              const cikisIso = trToIsoShift(p.istenCikis);
              const isPasif = (iso) => (girisIso && iso < girisIso) || (cikisIso && iso > cikisIso);
              return (
              <tr key={p.id}>
                <td style={{padding:"3px 6px",fontWeight:600,fontSize:11,whiteSpace:"nowrap",overflow:"hidden",maxWidth:120}}>{p.ad}</td>
                <td style={{padding:"3px 6px",fontWeight:600,fontSize:11,whiteSpace:"nowrap",overflow:"hidden",maxWidth:120}}>{p.soyad}</td>
                <td style={{padding:"3px 6px",fontSize:10,color:"var(--text-secondary)",whiteSpace:"nowrap",overflow:"hidden",maxWidth:110}}>{(p.gorev||"").substring(0,18)}</td>
                <td style={{padding:"3px 6px",fontSize:10,color:"var(--text-secondary)",whiteSpace:"nowrap",overflow:"hidden",maxWidth:100}}>{(p.departman||"").substring(0,16)}</td>
                <td style={{padding:"3px 4px",textAlign:"center",fontSize:10}}>{p.yiDevir||0}</td>
                {weekDays.map((iso,di)=>{
                  const cellKey=`${p.id}-${iso}`;
                  const kod=getShift(p.id,iso);
                  const pasif=isPasif(iso);
                  const isSel=selCells.has(cellKey);
                  const isDraftCell=draft[cellKey]!==undefined;
                  const onayBekleyen = onaylar.find(o=>String(o.pid)===String(p.id) && o.iso===iso && o.durum==="bekliyor");
                  const s=kod?shiftObj(kod):null;
                  const cellBg = isSel ? "#1e40af" : (kod ? (s?.bg||"#F1EFE8") : "transparent");

                  if(pasif) return (
                    <td key={iso} style={{background:"rgba(100,116,139,0.08)",textAlign:"center",padding:"2px"}}>
                      <span style={{display:"block",minWidth:36,minHeight:22}} />
                    </td>
                  );

                  return (
                    <td key={iso}
                      className={kod ? "shift-cell" : ""}
                      style={{
                        padding:"2px", textAlign:"center",
                        background: cellBg,
                        cursor: selectedShift?"crosshair":"pointer",
                        outline: isSel?"2px solid #60a5fa" : isDraftCell?"2px solid #f59e0b":"none",
                        outlineOffset:"-2px",
                        color: isSel?"#fff":"#000",
                        fontWeight:700, fontSize:12,
                      }}
                      onMouseDown={e=>handleMouseDown(pi,di,e)}
                      onMouseEnter={()=>handleMouseEnter(pi,di)}>
                      {onayBekleyen
                        ? <span style={{fontSize:10,fontWeight:700,color:s?.renk||"#854F0B",opacity:0.7}}>{kod||onayBekleyen.kod}</span>
                        : (kod||"")
                      }
                    </td>
                  );
                })}
                {opt.mesaiToplamGoster && (() => {
                  const toplamDk = weekDays.reduce((acc,iso)=>{
                    const k = getShift(p.id,iso);
                    const s = k ? SHIFTS.find(x=>x.kod===k) : null;
                    return acc + (s?.tanımliMesai || 0);
                  }, 0);
                  const saat = Math.floor(toplamDk/60);
                  const dk = toplamDk%60;
                  return <td style={{padding:"3px 6px",textAlign:"center",fontSize:11,fontWeight:600,color:"#185FA5",whiteSpace:"nowrap"}}>{saat>0||dk>0?`${saat}s ${dk}dk`:"—"}</td>;
                })()}
              </tr>
              );
            });
            })()}
            {filtered.length===0 && <tr><td colSpan={weekDays.length+3+(opt.mesaiToplamGoster?1:0)} style={{padding:24,textAlign:"center",color:"var(--text-tertiary)"}}>Bu departmanda personel yok</td></tr>}
          </tbody>
          <tfoot>
            {/* Her shift için ayrı satır — renksiz */}
            {siralanmisShifts(SHIFTS).filter(s=>{
              return weekDays.some(iso=>filtered.some(p=>getShift(p.id,iso)===s.kod));
            }).map(s=>(
              <tr key={s.kod}>
                <td colSpan={5} style={{padding:"3px 8px",fontSize:10,fontWeight:600,color:"var(--text-primary)"}}>{s.kod}{s.giris?` (${s.giris}-${s.cikis})`:""}</td>
                {weekDays.map(iso=>{
                  const n = filtered.filter(p=>getShift(p.id,iso)===s.kod).length;
                  return <td key={iso} style={{textAlign:"center",fontSize:10,fontWeight:600,color:"var(--text-primary)",padding:"3px 2px"}}>{n||""}</td>;
                })}
                {opt.mesaiToplamGoster && <td/>}
              </tr>
            ))}
            {/* İzin satırları — renksiz */}
            {IZINLER.filter(s=>weekDays.some(iso=>filtered.some(p=>getShift(p.id,iso)===s.kod))).map(s=>(
              <tr key={s.kod}>
                <td colSpan={5} style={{padding:"3px 8px",fontSize:10,fontWeight:600,color:"var(--text-primary)"}}>{s.kod} - {s.ad}</td>
                {weekDays.map(iso=>{
                  const n = filtered.filter(p=>getShift(p.id,iso)===s.kod).length;
                  return <td key={iso} style={{textAlign:"center",fontSize:10,fontWeight:600,color:"var(--text-primary)",padding:"3px 2px"}}>{n||""}</td>;
                })}
                {opt.mesaiToplamGoster && <td/>}
              </tr>
            ))}
            {/* Toplam İzin */}
            <tr style={{borderTop:"2px solid var(--grid-line)"}}>
              <td colSpan={5} style={{padding:"3px 8px",fontSize:10,fontWeight:700,color:"var(--text-primary)"}}>Toplam İzin</td>
              {weekDays.map((iso,i)=>{
                const n=filtered.filter(p=>IZINLER.some(iz=>iz.kod===getShift(p.id,iso))).length;
                return <td key={i} style={{textAlign:"center",fontSize:10,fontWeight:700,color:"var(--text-primary)",padding:"3px 2px"}}>{n||""}</td>;
              })}
              {opt.mesaiToplamGoster && <td/>}
            </tr>
            {/* Toplam Aktif */}
            <tr>
              <td colSpan={5} style={{padding:"3px 8px",fontSize:10,fontWeight:700,color:"var(--text-primary)"}}>Toplam Aktif</td>
              {weekDays.map((iso,i)=>{
                const n=filtered.filter(p=>SHIFTS.filter(s=>s.giris).some(s=>s.kod===getShift(p.id,iso))).length;
                return <td key={i} style={{textAlign:"center",fontSize:10,fontWeight:700,color:"var(--text-primary)",padding:"3px 2px"}}>{n||""}</td>;
              })}
              {opt.mesaiToplamGoster && <td/>}
            </tr>
            {/* Toplam Personel */}
            <tr>
              <td colSpan={5} style={{padding:"3px 8px",fontSize:10,fontWeight:700,color:"var(--text-primary)"}}>Toplam Personel</td>
              {weekDays.map((_,i)=><td key={i} style={{textAlign:"center",fontSize:10,fontWeight:700,color:"var(--text-primary)",padding:"3px 2px"}}>{filtered.length}</td>)}
              {opt.mesaiToplamGoster && <td/>}
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
  );
};

// ─── AYLIK PUANTAJ ───────────────────────────────────────────────────────────
// ─── SHIFT DATA STORE ────────────────────────────────────────────────────────
// key: "pid-YYYY-MM-DD", value: shift kodu
// Tüm atamaları localStorage'da saklar — ShiftAtama yazar, AylikPuantaj okur
const SHIFT_DATA_KEY = "pdks_shift_data";
const getShiftData = () => {
  try { const v=localStorage.getItem(SHIFT_DATA_KEY); return v?JSON.parse(v):{} } catch { return {}; }
};
const saveShiftData = (data) => {
  try { localStorage.setItem(SHIFT_DATA_KEY, JSON.stringify(data)); } catch {}
};

// Onay bekleyen store — format: {id, pid, iso, kod, tip, tarih, personelAd}
const ONAY_KEY = "pdks_onay_bekleyen";
const getOnayBekleyen = () => {
  try { const v=localStorage.getItem(ONAY_KEY); return v?JSON.parse(v):[]; } catch { return []; }
};
const saveOnayBekleyen = (liste) => {
  try { localStorage.setItem(ONAY_KEY, JSON.stringify(liste)); } catch {}
};

// 11 saat kuralı kontrolü: iki atama arası yeterli dinlenme var mı?
const onbirSaatKontrol = (pid, iso, yeniKod, mevcutData) => {
  const ss = shiftSaatleri(yeniKod);
  if(!ss) return true; // izin/OFF → kural yok
  const yeniBasDk = ss.baslangic;

  // Önceki gün
  const d = new Date(iso);
  d.setDate(d.getDate()-1);
  const oncekiIso = d.toISOString().slice(0,10);
  const oncekiKod = mevcutData[`${pid}-${oncekiIso}`];
  if(oncekiKod) {
    const oncekiSs = shiftSaatleri(oncekiKod);
    if(oncekiSs) {
      const oncekiBitisDk = oncekiSs.bitis; // gece yarısını geçen için 1440+
      // Önceki bitiş ile yeni başlangıç arası < 11 saat (660 dk)
      const fark = (yeniBasDk + 1440) - oncekiBitisDk; // gece geçişi için normalize
      const normalFark = fark > 1440 ? fark - 1440 : fark;
      if(normalFark < 660) return {ihlal:true, fark:normalFark, oncekiKod, oncekiIso};
    }
  }

  // Sonraki gün (yeni atama sonraki günün başlangıcını etkiler mi)
  const s2 = new Date(iso);
  s2.setDate(s2.getDate()+1);
  const sonrakiIso = s2.toISOString().slice(0,10);
  const sonrakiKod = mevcutData[`${pid}-${sonrakiIso}`];
  if(sonrakiKod) {
    const sonrakiSs = shiftSaatleri(sonrakiKod);
    if(sonrakiSs) {
      const yeniBitisDk = ss.bitis;
      const fark = (sonrakiSs.baslangic + 1440) - yeniBitisDk;
      const normalFark = fark > 1440 ? fark - 1440 : fark;
      if(normalFark < 660) return {ihlal:true, fark:normalFark, sonrakiKod, sonrakiIso};
    }
  }
  return {ihlal:false};
};

const AylikPuantaj = ({personeller, kullanici}) => {
  const izinliDeptler = kullanici?.yetki==="admin"
    ? [...new Set([...getDepartmanlar().map(d=>d.ad), ...personeller.map(p=>p.departman).filter(Boolean)])].sort()
    : (kullanici?.departmanlar||[]);
  const firmaP = getFirmaParams();
  const [dept, setDept] = useState(() => izinliDeptler.length===1 ? izinliDeptler[0] : "TÜMÜ");

  // Ay seçimi — bugünün ayı
  const bugunAy = `${_now.getFullYear()}-${pad2(_now.getMonth()+1)}`;
  const [selectedMonth, setSelectedMonth] = useState(bugunAy);

  // O ay için gün sayısı
  const [yil, ay] = selectedMonth.split("-").map(Number);
  const gunSayisi = new Date(yil, ay, 0).getDate();
  const days = Array.from({length:gunSayisi},(_,i)=>i+1);

  // Shift verisi — localStorage'dan
  const shiftData = getShiftData();

  const getKisiShift = (pid, gun) => {
    const iso = `${yil}-${pad2(ay)}-${pad2(gun)}`;
    return shiftData[`${pid}-${iso}`] || "";
  };

  const ayBasiIso = `${yil}-${pad2(ay)}-01`;
  const aySONUiso = `${yil}-${pad2(ay)}-${pad2(gunSayisi)}`;

  const filtered = personeller.filter(p => {
    if(kullanici?.yetki!=="admin" && !izinliDeptler.includes(p.departman)) return false;
    if(dept!=="TÜMÜ" && p.departman!==dept) return false;
    // İşten ayrılmış ve ayrılma tarihi bu aydan önceyse gösterme
    if(p.istenCikis) {
      const [g,m,y] = p.istenCikis.split(".");
      const cikisIso = `${y}-${m}-${g}`;
      if(cikisIso < ayBasiIso) return false;
    }
    // İşe girişi bu aydan sonraysa gösterme
    if(p.isGiris) {
      const [g,m,y] = p.isGiris.split(".");
      const girisIso = `${y}-${m}-${g}`;
      if(girisIso > aySONUiso) return false;
    }
    return true;
  });

  const CALISMA_KODLARI = new Set(SHIFTS.filter(s=>s.giris).map(s=>s.kod));
  const IZIN_KODLARI    = new Set(IZINLER.map(s=>s.kod).concat(["RT"]));
  const tumIzinler = getIzinler(); // dinamik izin sütunları için

  // Firma parametresinden puantaj çalışma yazısı
  const puantajYazisi = firmaP.puantajCalismaYazisi || "1";

  const [puantajTipi, setPuantajTipi] = useState("puantaj"); // puantaj | puantaj_renkli
  const [imzaTipi, setImzaTipi] = useState(""); // "" | imza_s | imza_gc
  const [secilenKisiId, setSecilenKisiId] = useState(null);
  const [yazParam, setYazParam] = useState({
    imzaAlani: true,
    istenAyrilanlariYazdirma: false,
    guncelTariheKadar: false,
    maasVeAgiYazdir: false,
    toplamlariGrupla: false,
  });
  const setYP = (k) => setYazParam(p=>({...p,[k]:!p[k]}));
  const filteredWithParam = filtered.filter(p => {
    if(yazParam.istenAyrilanlariYazdirma && p.istenCikis) return false;
    return true;
  });
  // Bilgiyi sayfa başlığına yaz
  React.useEffect(()=>{
    const el = document.getElementById("puantaj-bilgi");
    if(el) el.textContent = `${selectedMonth} · ${filtered.length} personel`;
    return ()=>{ const el=document.getElementById("puantaj-bilgi"); if(el) el.textContent=""; };
  }, [selectedMonth, filtered.length]);
  const bugunGun = _now.getFullYear()===yil && _now.getMonth()+1===ay ? _now.getDate() : null;
  const filteredDays = yazParam.guncelTariheKadar && bugunGun ? days.filter(d=>d<=bugunGun) : days;

  // Sadece o ay kullanılan izin kodlarını göster — dinamik sütunlar
  const kullanilanIzinler = React.useMemo(() => {
    const kullanilan = new Set();
    filteredWithParam.forEach(p => {
      filteredDays.forEach(g => {
        const s = getKisiShift(p.id, g);
        if(s && !CALISMA_KODLARI.has(s) && s !== "OFF") kullanilan.add(s);
      });
    });
    return tumIzinler.filter(iz => kullanilan.has(iz.kod));
  }, [filteredWithParam, filteredDays]);
  const getCellStyle = (kod) => {
    if(!kod) return {color:"var(--text-tertiary)"};
    if(puantajTipi==="puantaj_renkli") {
      const s = shiftObj(kod);
      return {background:s.bg, color:s.renk, fontWeight:600};
    }
    return {};
  };

  // - İzin/RT/OFF → kendi kodu
  // - Boş → —
  const getCellDisplay = (kod) => {
    if(!kod) return null;
    if(CALISMA_KODLARI.has(kod)) return puantajYazisi;
    return kod; // izin, OFF, RT kendi kodu
  };

  return (
    <div>
      {/* Tek satır toolbar */}
      <div style={{display:"flex",gap:8,marginBottom:8,alignItems:"center",flexWrap:"nowrap",overflowX:"auto"}}>
        <Select value={dept} onChange={e=>setDept(e.target.value)} style={{width:180,flexShrink:0}}>
          {izinliDeptler.length>1 && <option value="TÜMÜ">Tüm Departmanlar</option>}
          {izinliDeptler.map(d=><option key={d}>{d}</option>)}
        </Select>
        <input type="month" value={selectedMonth} onChange={e=>setSelectedMonth(e.target.value)}
          style={{padding:"7px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",colorScheme:"dark",flexShrink:0}} />
        <Btn primary><span style={{fontSize:16}}>📋</span><span>Listele</span></Btn>
        <Btn><span style={{fontSize:16}}>🖨️</span><span>Yazdır</span></Btn>

        {/* Rapor Türü */}
        <div style={{display:"flex",flexDirection:"column",justifyContent:"center",padding:"4px 10px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:6,flexShrink:0,alignSelf:"stretch"}}>
          <div style={{fontSize:9,fontWeight:700,color:"var(--text-secondary)",textTransform:"uppercase",letterSpacing:.05,marginBottom:3}}>Rapor Türü</div>
          <div style={{display:"flex",gap:10}}>
            <div style={{display:"flex",flexDirection:"column",gap:2}}>
              {[["puantaj","Aylık Puantaj"],["puantaj_renkli","Renkli"]].map(([val,lbl])=>(
                <label key={val} style={{display:"flex",alignItems:"center",gap:4,cursor:"pointer",fontSize:11,color:"var(--text-primary)",whiteSpace:"nowrap"}}>
                  <input type="radio" name="puantajTipi" checked={puantajTipi===val} onChange={()=>setPuantajTipi(val)} style={{margin:0}} />{lbl}
                </label>
              ))}
            </div>
            <div style={{width:1,background:"var(--grid-line)"}} />
            <div style={{display:"flex",flexDirection:"column",gap:2}}>
              {[["imza_s","İmza (S)"],["imza_gc","İmza (G/Ç)"]].map(([val,lbl])=>(
                <label key={val} style={{display:"flex",alignItems:"center",gap:4,cursor:"pointer",fontSize:11,color:"var(--text-primary)",whiteSpace:"nowrap"}}>
                  <input type="radio" name="imzaTipi" checked={imzaTipi===val} onChange={()=>setImzaTipi(imzaTipi===val?"":val)} style={{margin:0}} />{lbl}
                </label>
              ))}
            </div>
          </div>
        </div>

        {/* Yazdırma Parametreleri — 2 sütun */}
        <div style={{display:"flex",flexDirection:"column",justifyContent:"center",padding:"4px 10px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:6,flexShrink:0,alignSelf:"stretch"}}>
          <div style={{fontSize:9,fontWeight:700,color:"var(--text-secondary)",textTransform:"uppercase",letterSpacing:.05,marginBottom:3}}>Yazdırma Parametreleri</div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"2px 12px"}}>
            {[
              ["imzaAlani","İmza Alanı"],
              ["istenAyrilanlariYazdirma","Ayrılanları Yazdırma"],
              ["guncelTariheKadar","Güncel Tarihe Kadar"],
              ["maasVeAgiYazdir","Maaş ve AGİ"],
              ["toplamlariGrupla","Toplamları Grupla"],
            ].map(([key,lbl])=>(
              <label key={key} style={{display:"flex",alignItems:"center",gap:4,cursor:"pointer",fontSize:11,color:"var(--text-primary)",whiteSpace:"nowrap"}}>
                <input type="checkbox" checked={yazParam[key]} onChange={()=>setYP(key)} style={{margin:0}} />{lbl}
              </label>
            ))}
          </div>
        </div>

      </div>

      <div style={{overflowX:"auto"}}>
        <table className="pdks-table" style={{borderCollapse:"collapse",fontSize:11,tableLayout:"fixed"}}>
          <thead>
            <tr>
              <th style={{textAlign:"left",minWidth:130,position:"sticky",left:0,zIndex:2,background:"var(--th-bg)"}}>Personel</th>
              <th style={{minWidth:90,fontSize:10}}>Görevi</th>
              <th style={{width:28,fontSize:10,textAlign:"center"}} title="Toplam Puan">TP</th>
              <th style={{width:28,fontSize:10,textAlign:"center"}} title="Çalışma Toplam">ÇT</th>
              {kullanilanIzinler.map(iz=>(
                <th key={iz.kod} style={{width:28,fontSize:10,textAlign:"center",color:iz.renk}} title={iz.ad}>{iz.kod}</th>
              ))}
              <th style={{width:28,fontSize:10,textAlign:"center"}} title="Boş (atama yok)">?</th>
              {filteredDays.map(d=>(
                <th key={d} style={{width:22,padding:"3px 1px",textAlign:"center",
                  background: new Date(yil,ay-1,d).getDay()===0||new Date(yil,ay-1,d).getDay()===6
                    ? "rgba(255,255,255,0.08)" : undefined}}>
                  <div style={{fontSize:9,opacity:.6}}>{["Pz","Pt","Sa","Ça","Pe","Cu","Cm"][new Date(yil,ay-1,d).getDay()]}</div>
                  <div>{d}</div>
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {filteredWithParam.map((p,pi)=>{
              const dayShifts = filteredDays.map(g => getKisiShift(p.id, g));
              const ct  = dayShifts.filter(s=>CALISMA_KODLARI.has(s)).length;
              const off = dayShifts.filter(s=>s==="OFF").length;
              const bos = dayShifts.filter(s=>!s).length;
              // TP hesaplama — çalışma + ücretli izinler
              const ucretliIzinKodlari = new Set(kullanilanIzinler.filter(i=>i.tip!=="ucretsiz").map(i=>i.kod));
              const toplamIzin = dayShifts.filter(s=>ucretliIzinKodlari.has(s)).length;
              let tp = ct + toplamIzin;

              // "Puantaj Toplamı 30 Gün Alsın" — 31 günlük ayda max 30
              if(firmaP.puantajToplami30GunAlsin) {
                tp = Math.min(tp, 30);
              }

              // İşe giriş/çıkış tarih kontrolü
              const girisIso = (() => {
                if(!p.isGiris) return null;
                const [g,m,y]=p.isGiris.split("."); return `${y}-${m}-${g}`;
              })();
              const cikisIso = (() => {
                if(!p.istenCikis) return null;
                const [g,m,y]=p.istenCikis.split("."); return `${y}-${m}-${g}`;
              })();
              const gunIso = (g) => `${yil}-${pad2(ay)}-${pad2(g)}`;

              const getCellBg = (g) => {
                const iso = gunIso(g);
                if(girisIso && iso < girisIso) return "rgba(100,116,139,0.12)"; // henüz işe girmemiş — gri
                if(cikisIso && iso > cikisIso) return "rgba(163,45,45,0.08)";   // işten ayrılmış — kırmızımsı
                return undefined;
              };
              const getCellContent = (s, g) => {
                const iso = gunIso(g);
                if(girisIso && iso < girisIso) return "pasif";
                if(cikisIso && iso > cikisIso) return "pasif";
                return s;
              };

              const isSecili = secilenKisiId===p.id;
              return (
                <tr key={p.id}
                  onClick={()=>setSecilenKisiId(isSecili?null:p.id)}
                  style={{cursor:"pointer",background:isSecili?"rgba(21,101,160,0.18)":undefined,outline:isSecili?"2px solid #1565A0":"none",outlineOffset:"-2px"}}>
                  <td style={{fontWeight:isSecili?700:500,position:"sticky",left:0,background:isSecili?"rgba(21,101,160,0.18)":pi%2?"var(--tr-even)":"var(--card-bg)",zIndex:1,padding:"4px 8px"}}>
                    {p.ad} {p.soyad}
                    {cikisIso && <span style={{marginLeft:4,fontSize:9,color:"#A32D2D",fontWeight:600}}>✕{p.istenCikis}</span>}
                  </td>
                  <td style={{fontSize:10,color:"var(--text-secondary)",padding:"4px 6px"}}>{(p.gorev||"").substring(0,14)}</td>
                  <td style={{textAlign:"center",fontWeight:600,padding:"4px 2px"}}>{tp||""}</td>
                  <td style={{textAlign:"center",padding:"4px 2px"}}>{ct||""}</td>
                  {kullanilanIzinler.map(iz=>{
                    const sayi = dayShifts.filter(s=>s===iz.kod).length;
                    return <td key={iz.kod} style={{textAlign:"center",padding:"4px 2px",color:sayi?iz.renk:undefined,fontWeight:sayi?600:400}}>{sayi||""}</td>;
                  })}
                  <td style={{textAlign:"center",padding:"4px 2px",color:bos?"#A32D2D":undefined,fontWeight:bos?600:400}}>{bos||""}</td>
                  {dayShifts.map((s,di)=>{
                    const g = days[di];
                    const rawContent = getCellContent(s, g);
                    const isPasif = rawContent === "pasif";
                    const display = isPasif ? null : getCellDisplay(rawContent);
                    // Çalışma vardiyası için tooltip olarak gerçek shift kodu
                    const tooltip = s && CALISMA_KODLARI.has(s) ? `${s} vardiyası` : "";
                    const bg = getCellBg(g);
                    return (
                      <td key={di} style={{padding:"1px",textAlign:"center",background:isPasif?bg:undefined}}>
                        {isPasif
                          ? <span style={{color:"rgba(150,150,150,0.3)",fontSize:9}}>—</span>
                          : display
                            ? <span title={tooltip} style={{
                                ...getCellStyle(s),
                                padding:"1px 2px",borderRadius:2,fontSize:10,
                                display:"inline-block",minWidth:18,textAlign:"center",fontWeight:600
                              }}>{display}</span>
                            : <span style={{color:"var(--grid-line)",fontSize:9}}>·</span>
                        }
                      </td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
          <tfoot>
            <tr style={{borderTop:"2px solid var(--grid-line)"}}>
              <td colSpan={2} style={{padding:"4px 8px",fontSize:11,fontWeight:600,color:"var(--text-secondary)"}}>Günlük Özet</td>
              <td colSpan={7}></td>
              {days.map(g=>{
                const gunShiftler = filtered.map(p=>getKisiShift(p.id,g)).filter(Boolean);
                const calisanlar = gunShiftler.filter(s=>CALISMA_KODLARI.has(s)).length;
                return (
                  <td key={g} style={{padding:"1px",textAlign:"center",fontSize:9,verticalAlign:"top"}}>
                    {calisanlar>0 && <div style={{background:"#EAF3DE",color:"#3B6D11",borderRadius:2,padding:"1px 2px",marginBottom:1,fontWeight:600}}>{calisanlar}</div>}
                  </td>
                );
              })}
            </tr>
          </tfoot>
        </table>
      </div>

      {filtered.some(p=>days.some(g=>!getKisiShift(p.id,g))) && (
        <div style={{marginTop:10,padding:"8px 14px",background:"#FAEEDA",border:"1px solid #854F0B",borderRadius:8,fontSize:12,color:"#854F0B"}}>
          ⚠️ "?" sütununda gösterilen günlerde shift ataması yapılmamış. Shift Atama ekranından eksikleri tamamlayın.
        </div>
      )}
    </div>
  );
};

// ─── SÜRÜKLENEBILIR + SIRALAMALΙ TABLO ───────────────────────────────────────
const DraggableTable = ({cols, setCols, hiddenCols, setHiddenCols, children, tableClass="pdks-table", onSortChange}) => {
  const dragIdx = useRef(null);
  const [showPicker, setShowPicker] = useState(false);
  const [sortCol, setSortCol] = useState(null);
  const [sortDir, setSortDir] = useState(0); // 0=normal 1=A-Z 2=Z-A
  const pickerRef = useRef(null);

  useEffect(()=>{
    if(!showPicker) return;
    const handler = (e)=>{ if(pickerRef.current && !pickerRef.current.contains(e.target)) setShowPicker(false); };
    document.addEventListener("mousedown", handler);
    return ()=>document.removeEventListener("mousedown", handler);
  },[showPicker]);

  const handleSort = (col) => {
    let newCol = sortCol, newDir = sortDir;
    if(sortCol !== col) { newCol=col; newDir=1; }
    else if(sortDir===1) { newDir=2; }
    else if(sortDir===2) { newCol=null; newDir=0; }
    else { newCol=col; newDir=1; }
    setSortCol(newCol); setSortDir(newDir);
    onSortChange?.({col:newCol, dir:newDir});
  };

  const sortIcon = (col) => {
    if(sortCol!==col) return <span style={{opacity:.2,fontSize:9,marginLeft:3,fontWeight:"normal"}}>⇅</span>;
    return <span style={{fontSize:9,marginLeft:3,color:"#93c5fd"}}>{sortDir===1?"▲":"▼"}</span>;
  };

  const onDragStart = (i) => { dragIdx.current = i; };
  const onDragOver = (e, i) => {
    e.preventDefault();
    if(dragIdx.current===null||dragIdx.current===i) return;
    const next=[...cols]; const [moved]=next.splice(dragIdx.current,1);
    next.splice(i,0,moved); dragIdx.current=i; setCols(next);
  };
  const onDragEnd = () => { dragIdx.current = null; };

  const visibleCols = cols.filter(c=>!hiddenCols.has(c));

  return (
    <div>
      <div style={{display:"flex",justifyContent:"flex-end",marginBottom:6,position:"relative"}} ref={pickerRef}>
        <button onClick={()=>setShowPicker(p=>!p)} style={{padding:"5px 12px",border:"1px solid var(--input-border)",borderRadius:6,background:showPicker?"var(--th-bg)":"var(--input-bg)",color:showPicker?"#fff":"var(--text-secondary)",fontSize:11,cursor:"pointer",display:"flex",alignItems:"center",gap:5,fontFamily:"var(--font-sans)"}}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M3 12h18M3 6h18M3 18h18"/></svg>
          Sütunlar ({visibleCols.length}/{cols.length})
        </button>
        {showPicker && (
          <div style={{position:"absolute",top:"calc(100% + 4px)",right:0,background:"var(--card-bg)",border:"1px solid var(--input-border)",borderRadius:8,zIndex:999,width:220,boxShadow:"0 8px 24px rgba(0,0,0,.3)",display:"flex",flexDirection:"column"}}>
            <div style={{padding:"10px 14px 6px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center",flexShrink:0}}>
              <span style={{fontSize:11,fontWeight:700,color:"var(--text-secondary)",letterSpacing:.06}}>SÜTUNLARI SEÇ</span>
              <div style={{display:"flex",gap:6}}>
                <button onClick={()=>setHiddenCols(new Set())} style={{fontSize:10,border:"none",background:"none",cursor:"pointer",color:"#185FA5",padding:"2px 4px",fontFamily:"var(--font-sans)"}}>Tümü</button>
                <button onClick={()=>setHiddenCols(new Set(cols))} style={{fontSize:10,border:"none",background:"none",cursor:"pointer",color:"#A32D2D",padding:"2px 4px",fontFamily:"var(--font-sans)"}}>Temizle</button>
              </div>
            </div>
            <div style={{overflowY:"auto",maxHeight:280,padding:"4px 0"}}>
              {cols.map(col=>(
                <label key={col} style={{display:"flex",alignItems:"center",gap:10,padding:"6px 14px",cursor:"pointer",fontSize:12,color:"var(--text-primary)"}} onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"} onMouseLeave={e=>e.currentTarget.style.background=""}>
                  <input type="checkbox" checked={!hiddenCols.has(col)} onChange={e=>{
                    setHiddenCols(prev=>{const n=new Set(prev); e.target.checked?n.delete(col):n.add(col); return n;});
                  }} />
                  <span style={{flex:1}}>{col}</span>
                </label>
              ))}
            </div>
          </div>
        )}
      </div>
      <div style={{overflowX:"auto"}}>
        <table className={tableClass} style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
          <thead>
            <tr>
              {visibleCols.map(col=>(
                <th key={col} draggable
                  onDragStart={()=>onDragStart(cols.indexOf(col))}
                  onDragOver={e=>onDragOver(e,cols.indexOf(col))}
                  onDragEnd={onDragEnd}
                  onClick={()=>handleSort(col)}
                  title="Sıralamak için tıkla, sürükle yerini değiştir"
                  style={{cursor:"pointer",userSelect:"none",whiteSpace:"nowrap",background:sortCol===col?"#0d4f8a":undefined,transition:"background .1s"}}>
                  {col}{sortIcon(col)}
                </th>
              ))}
            </tr>
          </thead>
          {children}
        </table>
      </div>
    </div>
  );
};

const PersonelHareketleri = ({personeller, uid="guest"}) => {
  const HAREKET_KEY = "pdks_hareketler";
  const loadHareketler = () => { try { const v=localStorage.getItem(HAREKET_KEY); return v?JSON.parse(v):null; } catch { return null; } };
  const saveHareketler = (data) => { try { localStorage.setItem(HAREKET_KEY, JSON.stringify(data)); } catch {} };

  const hesaplaHatalar = (liste) => liste.map(h => {
    const ss = shiftSaatleri(h.shiftKod);
    const girisToler = ss?.girisToler || 30;
    const hatalar = hataDetect(h.shiftKod, h.gGiris, h.gCikis, h.tarih, BUGUN_TARIH, girisToler);
    return {...h, hatalar, hatali: hatalar.length > 0};
  });

  const [hareketler, setHareketler] = useState(() => {
    const saved = loadHareketler();
    if(saved && saved.length > 0) return hesaplaHatalar(saved);
    return hesaplaHatalar(TUM_HAREKETLER.map(h=>({...h})));
  });

  const [dept, setDept] = useState("TÜMÜ");
  const [seciliPersonelId, setSeciliPersonelId] = useState("TÜMÜ");
  const [basTarih, setBasTarih] = useState(BUGUN_ISO);
  const [bitTarih, setBitTarih] = useState(BUGUN_ISO);
  // Listeleme parametreleri — sadece Listele butonuna basınca güncellenir
  const [listeParams, setListeParams] = useState({bas:BUGUN_ISO, bit:BUGUN_ISO, dept:"TÜMÜ", pid:"TÜMÜ"});
  const handleListele = () => setListeParams({bas:basTarih, bit:bitTarih, dept, pid:seciliPersonelId});
  const [shiftFiltre, setShiftFiltre] = useState("TÜMÜ"); // "TÜMÜ" | shift kodu
  const [hataFiltre, setHataFiltre] = useState("TÜMÜ"); // "TÜMÜ"|"MESAI_GIRILENLER"|"OKUTMA_UNUTANLAR"|"OKUTMA_UNUTANLAR_ANT"|"SHIFTE_UYMAYANLAR"|"TUM_HATALI"|"SHIFT_ATANMAYANLAR" | izin kodu
  const [kisiModalId, setKisiModalId] = useState(null);
  const [editCell, setEditCell] = useState(null);
  const [editVal, setEditVal] = useState("");
  const [ctxMenu, setCtxMenu] = useState(null);
  const [ctxSubMenu, setCtxSubMenu] = useState(null);
  const [sortState, setSortState] = useState({col:null,dir:0});
  const [selCells, setSelCells] = useState(new Set());
  const isDragging = React.useRef(false);
  const dragStart = React.useRef(null);
  const COLS = ["ADI","SOYADI","DEPARTMAN","GÖREV","TARİH","SHIFT","G.GİRİŞ","G.ÇIKIŞ","ANTRACT","A.ÇIKIŞ","A.GİRİŞ","MESAİ","Ö.TİPİ","Ö.MESAİ"];
  const [cols, setCols, hiddenCols, setHiddenCols] = usePersistentCols(uid, "giris", COLS);
  const COL_KEY_H = {"ADI":"ad","SOYADI":"soyad","DEPARTMAN":"departman","GÖREV":"gorev","TARİH":"tarih","SHIFT":"shiftKod","G.GİRİŞ":"gGiris","G.ÇIKIŞ":"gCikis","MESAİ":"mesai"};

  const isoToTr = (iso) => { const [y,m,g]=iso.split("-"); return `${g}.${m}.${y}`; };
  const trToNum = (tr) => { if(!tr) return 0; const [g,m,y]=tr.split("."); return parseInt(`${y}${m}${g}`); };

  const guncelleHareket = (id, tarih, field, val, hayaletSatir=null) => {
    setHareketler(prev => {
      const tarihAlt = tarih.includes("-")
        ? tarih.split("-").reverse().join(".")
        : tarih.split(".").reverse().join("-");
      const bul = (r) => String(r.id)===String(id) && (r.tarih===tarih || r.tarih===tarihAlt);
      const mevcutVar = prev.some(bul);
      let liste = prev;
      if(!mevcutVar && hayaletSatir) {
        liste = [...prev, {...hayaletSatir, _hayalet:false}];
      }
      const yeni = liste.map(r => {
        if(!bul(r)) return r;
        const updated = {...r, [field]: val};
        const ss = shiftSaatleri(updated.shiftKod);
        const girisToler = ss?.girisToler || 30;
        const hatalar = hataDetect(updated.shiftKod, updated.gGiris, updated.gCikis, updated.tarih, BUGUN_TARIH, girisToler);
        return {...updated, hatalar, hatali: hatalar.length>0};
      });
      saveHareketler(yeni); return yeni;
    });
  };

  const saveEdit = () => {
    if(!editCell) return;
    if(editCell.field === "mesai") {
      setHareketler(prev => {
        const yeni = prev.map(r => {
          if(r.id !== editCell.id || r.tarih !== editCell.tarih) return r;
          const degisti = editVal.trim() !== (r.mesai || "");
          return {...r, mesai: editVal, mesaiManuel: degisti ? true : r.mesaiManuel, mesaiAuto: degisti ? false : r.mesaiAuto};
        });
        saveHareketler(yeni); return yeni;
      });
    } else {
      guncelleHareket(editCell.id, editCell.tarih, editCell.field, editVal);
    }
    setEditCell(null);
  };

  // Hata tipi renk
  const hataTipiRenk = (tip) => {
    if(tip==="GİRİŞ YOK"||tip==="ÇIKIŞ YOK") return {bg:"#FCEBEB",c:"#A32D2D"};
    if(tip==="GEÇ GİRİŞ"||tip==="ERKEN ÇIKIŞ") return {bg:"#FAEEDA",c:"#854F0B"};
    if(tip==="ERKEN GİRİŞ"||tip==="GEÇ ÇIKIŞ") return {bg:"#FFF3CD",c:"#7A5500"};
    if(tip==="İZİNDE ÇALIŞTI") return {bg:"#F3E8FF",c:"#6B21A8"};
    return {bg:"#F1EFE8",c:"#5F5E5A"};
  };

  // Satır arkaplan rengi — hata durumuna göre
  const satirRenk = (h) => {
    if(!h.hatalar || h.hatalar.length===0) return undefined;
    const tipler = h.hatalar.map(x=>x.tip);
    if(tipler.some(t=>t==="GİRİŞ YOK"||t==="ÇIKIŞ YOK")) return "rgba(163,45,45,0.12)";
    if(tipler.some(t=>t==="GEÇ GİRİŞ"||t==="ERKEN ÇIKIŞ")) return "rgba(133,79,11,0.10)";
    if(tipler.some(t=>t==="ERKEN GİRİŞ"||t==="GEÇ ÇIKIŞ")) return "rgba(200,180,0,0.10)";
    return undefined;
  };

  // Hücre rengi — giriş/çıkış saati hata içeriyorsa
  const saatRenk = (h, tipKelime) => {
    if(!h.hatalar) return undefined;
    if(h.hatalar.some(x=>x.tip.includes(tipKelime))) return {bg:"#FFF3CD",c:"#7A5500"};
    return undefined;
  };

  // Saat hücresi — tıklanabilir, düzenlenebilir
  const SaatCell = ({h, field, val, hataTip}) => {
    const isEdit = editCell?.id===h.id && editCell?.tarih===h.tarih && editCell?.field===field;
    const isOff = h.shiftKod==="OFF" || IZIN_KODLARI.has(h.shiftKod);
    if(isEdit) return (
      <input type="time" value={editVal} autoFocus
        onChange={e=>{
          const v = e.target.value;
          setEditVal(v);
          // Anında kaydet — blur bekleme
          guncelleHareket(h.id, h.tarih, field, v);
        }}
        onBlur={()=>setEditCell(null)}
        onKeyDown={e=>{ if(e.key==="Escape") setEditCell(null); }}
        style={{width:70,padding:"2px 4px",border:"2px solid #1565A0",borderRadius:4,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:12,fontFamily:"monospace"}}
      />
    );
    const hataVar = !isOff && h.hatalar?.some(x=>x.tip.includes(hataTip||""));
    const cellBg = hataVar ? (hataTip==="GİRİŞ"?(h.hatalar?.some(x=>x.tip==="GİRİŞ YOK")?"#FCEBEB":"#FFF3CD"):(h.hatalar?.some(x=>x.tip==="ÇIKIŞ YOK")?"#FCEBEB":"#FFF3CD")) : undefined;
    const cellC  = hataVar ? (h.hatalar?.some(x=>x.tip.includes("YOK"))?"#A32D2D":"#7A5500") : undefined;
    return (
      <span
        onMouseUp={e=>{
          if(isDragging.current) return; // sürükleme varsa düzenleme açma
          e.stopPropagation();
          setEditCell({id:h.id, tarih:h.tarih, field});
          setEditVal(val||"");
        }}
        title="Tıkla — düzenle"
        style={{display:"inline-block",cursor:"text",padding:"1px 5px",borderRadius:4,border:"1px solid transparent",minWidth:52,fontFamily:"monospace",fontSize:12,
          background:cellBg, color:cellC||(isOff&&!val?"var(--text-tertiary)":"var(--text-primary)"), fontWeight:hataVar?700:400}}
        onMouseEnter={e=>{ if(!cellBg) e.currentTarget.style.border="1px solid var(--input-border)"; }}
        onMouseLeave={e=>{ if(!cellBg) e.currentTarget.style.border="1px solid transparent"; }}>
        {val || <span style={{color:hataVar?"#A32D2D":"var(--text-tertiary)",fontSize:11,fontWeight:hataVar?700:400}}>—</span>}
      </span>
    );
  };

  const cellVal = (h, col) => {
    const s = shiftObj(h.shiftKod);
    switch(col) {
      case "ADI":       return (
        <span onClick={()=>setKisiModalId(h.id)} title="Kişinin tüm hareketlerini gör"
          style={{fontWeight:600,cursor:"pointer",textDecoration:"underline dotted",textUnderlineOffset:3}}>
          {h.ad}
        </span>
      );
      case "SOYADI":    return h.soyad;
      case "DEPARTMAN": return <span style={{color:"var(--text-secondary)"}}>{h.departman}</span>;
      case "GÖREV":     return <span style={{color:"var(--text-secondary)",fontSize:11}}>{h.gorev}</span>;
      case "TARİH":     return h.tarih;
      case "SHIFT":     return <span style={{background:s.bg,color:s.renk,padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:600,whiteSpace:"nowrap"}}>{h.shiftKod}{s.giris?` (${s.giris}-${s.cikis})`:""}</span>;
      case "G.GİRİŞ":  return <SaatCell h={h} field="gGiris" val={h.gGiris} hataTip="GİRİŞ" />;
      case "G.ÇIKIŞ":  return <SaatCell h={h} field="gCikis" val={h.gCikis} hataTip="ÇIKIŞ" />;      case "ANTRACT":   return <span style={{color:"var(--text-tertiary)"}}>{h.antract||"—"}</span>;
      case "A.ÇIKIŞ":   return <span style={{color:"var(--text-tertiary)"}}>{h.aCikis||"—"}</span>;
      case "A.GİRİŞ":   return <span style={{color:"var(--text-tertiary)"}}>{h.aGiris||"—"}</span>;
      case "MESAİ": {
        const isMesaiEdit = editCell?.id===h.id && editCell?.tarih===h.tarih && editCell?.field==="mesai";
        if(isMesaiEdit) return (
          <input type="text" value={editVal} autoFocus placeholder="1.30"
            onChange={e=>setEditVal(e.target.value)}
            onBlur={saveEdit}
            onKeyDown={e=>{ if(e.key==="Enter") saveEdit(); if(e.key==="Escape") setEditCell(null); }}
            style={{width:60,padding:"2px 4px",border:"2px solid #1565A0",borderRadius:4,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:12,fontFamily:"monospace"}}
          />
        );
        return (
          <span onClick={()=>{ setEditCell({id:h.id,tarih:h.tarih,field:"mesai"}); setEditVal(h.mesai||""); }}
            title={h.mesaiManuel?"Elle girildi":h.mesaiAuto?"Otomatik hesaplandı":"Düzenle"}
            style={{cursor:"text",display:"inline-flex",alignItems:"center",gap:4,padding:"2px 6px",borderRadius:4,border:"1px solid transparent",
              color:h.mesai&&h.mesai!=="0.00"?"var(--text-primary)":"var(--text-tertiary)",fontWeight:h.mesai&&h.mesai!=="0.00"?600:400}}
            onMouseEnter={e=>e.currentTarget.style.border="1px solid var(--input-border)"}
            onMouseLeave={e=>e.currentTarget.style.border="1px solid transparent"}>
            {h.mesai||"0.00"}
            {h.mesaiManuel&&<span style={{fontSize:9,background:"#FAEEDA",color:"#854F0B",padding:"0 4px",borderRadius:3,fontWeight:700}}>M</span>}
          </span>
        );
      }
      case "Ö.TİPİ":    return <span style={{color:"var(--text-tertiary)"}}>{h.oTipi||"—"}</span>;
      case "Ö.MESAİ":   return h.oMesai;
      default: return "—";
    }
  };

  // Ağır hesaplamalar için listeParams kullan (sadece Listele butonunda güncellenir)
  const basNum = trToNum(isoToTr(listeParams.bas));
  const bitNum = trToNum(isoToTr(listeParams.bit));

  const IZINLER_GUNCEL = getIzinler();
  const IZIN_KODLARI = new Set(IZINLER_GUNCEL.map(i=>i.kod));
  const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();

  const tarihAraligi = (() => {
    const gunler = [];
    const bas = new Date(listeParams.bas), bit = new Date(listeParams.bit);
    for(let d=new Date(bas); d<=bit; d.setDate(d.getDate()+1))
      gunler.push(d.toISOString().slice(0,10));
    return gunler;
  })();

  const shifttenGelenSatirlar = (() => {
    const satırlar = [];
    tarihAraligi.forEach(iso => {
      personeller.forEach(p => {
        if(listeParams.dept!=="TÜMÜ" && p.departman!==listeParams.dept) return;
        if(listeParams.pid!=="TÜMÜ" && String(p.id)!==String(listeParams.pid)) return;
        const shiftKod = shiftData[`${p.id}-${iso}`];
        if(!shiftKod) return;
        const tarihTR = iso.split("-").reverse().join(".");
        const hareketVar = hareketler.some(h =>
          String(h.id)===String(p.id) && (h.tarih===iso || h.tarih===tarihTR)
        );
        if(!hareketVar) {
          if(IZIN_KODLARI.has(shiftKod)) return;
          const hayaletHatalar = [{tip:"GİRİŞ YOK", aciklama:"Cihazda giriş kaydı bulunamadı"}, {tip:"ÇIKIŞ YOK", aciklama:"Cihazda çıkış kaydı bulunamadı"}];
          satırlar.push({
            id: p.id, ad: p.ad, soyad: p.soyad,
            departman: p.departman, gorev: p.gorev,
            tarih: tarihTR, shiftKod,
            gGiris: "", gCikis: "",
            hatalar: hayaletHatalar,
            hatali: true, mesai: "0.00",
            _hayalet: true
          });
        }
      });
    });
    return satırlar;
  })();

  const tumSatirlar = (() => {
    const gercek = hareketler.filter(h => {
      const tNum = trToNum(h.tarih);
      if(tNum < basNum || tNum > bitNum) return false;
      if(listeParams.dept!=="TÜMÜ" && h.departman!==listeParams.dept) return false;
      if(listeParams.pid!=="TÜMÜ" && String(h.id)!==String(listeParams.pid)) return false;
      return true;
    });
    return [...gercek, ...shifttenGelenSatirlar];
  })();

  // Shift ve Hata filtrelerini uygula (dept/pid zaten tumSatirlar'da filtrelendi)
  const filtered = tumSatirlar.filter(h => {
    // Shift filtresi
    if(shiftFiltre!=="TÜMÜ") {
      if(shiftFiltre==="TUM_IZINLER") { if(!IZIN_KODLARI.has(h.shiftKod)) return false; }
      else if(shiftFiltre==="TUM_SHIFTLER") { if(IZIN_KODLARI.has(h.shiftKod)) return false; }
      else { if(h.shiftKod!==shiftFiltre) return false; }
    }
    // Hata filtresi
    if(hataFiltre!=="TÜMÜ") {
      if(hataFiltre==="MESAI_GIRILENLER") return h.mesai && h.mesai!=="0.00";
      if(hataFiltre==="OKUTMA_UNUTANLAR") return !h.gGiris || !h.gCikis;
      if(hataFiltre==="OKUTMA_UNUTANLAR_ANT") return !h.gCikis;
      if(hataFiltre==="SHIFTE_UYMAYANLAR") return h.hatali && !(!h.gGiris);
      if(hataFiltre==="TUM_HATALI") return h.hatali;
      if(hataFiltre==="IZINDE_CALISTI") return h.hatalar?.some(x=>x.tip==="İZİNDE ÇALIŞTI");
      if(hataFiltre==="SHIFT_ATANMAYANLAR") { const tarihISO=h.tarih.includes("-")?h.tarih:h.tarih.split(".").reverse().join("-"); return !shiftData[`${h.id}-${tarihISO}`]; }
      // İzin kodu seçilmişse
      if(IZIN_KODLARI.has(hataFiltre)) return h.shiftKod===hataFiltre;
    }
    return true;
  });

  const hatalilar = filtered.filter(h=>h.hatali);

  const sortedFiltered = (() => {
    const {col,dir} = sortState;
    if(!col||dir===0) return filtered;
    return [...filtered].sort((a,b)=>{
      // Tarih sütunu için sayısal sıralama (DD.MM.YYYY → YYYYMMDD)
      if(col==="TARİH") {
        const toNum = (t) => {
          if(!t) return 0;
          const p = t.includes("-") ? t.split("-") : t.split(".").reverse();
          return parseInt(p.join(""));
        };
        const c = toNum(a.tarih) - toNum(b.tarih);
        return dir===1?c:-c;
      }
      const key = COL_KEY_H[col]||col.toLowerCase();
      const va=String(a[key]??"").toLowerCase(), vb=String(b[key]??"").toLowerCase();
      const c=va.localeCompare(vb,"tr",{numeric:true});
      return dir===1?c:-c;
    });
  })();

  // Seçim fonksiyonları — sortedFiltered'dan SONRA tanımlanmalı
  const getRange = (a, b) => {
    if(!a||!b) return new Set();
    const minR=Math.min(a.pi,b.pi), maxR=Math.max(a.pi,b.pi);
    const minC=Math.min(a.di,b.di), maxC=Math.max(a.di,b.di);
    const s=new Set();
    for(let r=minR;r<=maxR;r++)
      for(let cc=minC;cc<=maxC;cc++)
        if(sortedFiltered[r]) s.add(`${sortedFiltered[r].id}-${sortedFiltered[r].tarih}-${cc}`);
    return s;
  };
  const hMD = (pi,di,e) => { e.preventDefault(); isDragging.current=true; dragStart.current={pi,di}; setSelCells(getRange({pi,di},{pi,di})); };
  const hME = (pi,di) => { if(!isDragging.current) return; setSelCells(getRange(dragStart.current,{pi,di})); };
  const hMU = () => { isDragging.current=false; };

  // Mesai hesaplama fonksiyonu — sadece filtered'daki (ekranda görünen) kayıtlar
  const hesaplaMesai = () => {
    const basTarih=basTarihD, bitTarih=bitTarihD;
    let n = 0;
    // filtered'daki id-tarih çiftlerini set olarak al
    const filteredKeys = new Set(filtered.map(h=>`${h.id}-${h.tarih}`));
    setHareketler(prev => {
      const yeni = prev.map(h => {
        if(!filteredKeys.has(`${h.id}-${h.tarih}`)) return h; // filtrede yok → dokunma
        if(!h.gGiris || !h.gCikis) return h;
        if(h.mesaiManuel) return h;
        const ss = shiftSaatleri(h.shiftKod);
        const gG = saatDk(h.gGiris), cG = saatDk(h.gCikis);
        if(gG===null||cG===null) return h;
        let mesaiDk = 0;
        if(ss) {
          const girisToler=ss.girisToler||30, cikisToler=ss.cikisToler||30;
          let cikisDuz=cG; if(ss.bitis>1440&&cikisDuz<gG) cikisDuz+=1440; else if(cikisDuz<gG) cikisDuz+=1440;
          const efG = Math.abs(gG-ss.baslangic)<=girisToler ? ss.baslangic : gG;
          const taban = ss.bitis+cikisToler;
          const fazla = cikisDuz-taban;
          mesaiDk = fazla<=0 ? 0 : Math.floor(fazla/30)*30;
        } else {
          let cikisDuz=cG; if(cikisDuz<gG) cikisDuz+=1440;
          mesaiDk = Math.max(0, cikisDuz-gG-480);
        }
        n++;
        const mesaiStr = mesaiDk<=0 ? "0.00" : `${Math.floor(mesaiDk/60)}.${String(mesaiDk%60).padStart(2,"0")}`;
        return {...h, mesai:mesaiStr, mesaiAuto:true};
      });
      saveHareketler(yeni); return yeni;
    });
    setTimeout(()=>alert(`✓ ${n} kayıt için mesai hesaplandı.`),50);
  };

  const inputStyle = {padding:"6px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--card-bg)",fontSize:13,color:"var(--text-primary)",colorScheme:"dark"};

  // Personel listesi (departman filtresine göre)
  const personelSecenekleri = personeller.filter(p => dept==="TÜMÜ" || p.departman===dept);

  // Özet sayaçlar
  const girisYok   = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="GİRİŞ YOK")).length;
  const cikisYok   = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="ÇIKIŞ YOK")).length;
  const gecGiris   = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="GEÇ GİRİŞ")).length;
  const erkenGiris = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="ERKEN GİRİŞ")).length;
  const erkenCikis = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="ERKEN ÇIKIŞ")).length;
  const gecCikis   = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="GEÇ ÇIKIŞ")).length;
  const izindeCalisti = filtered.filter(h=>h.hatalar?.some(x=>x.tip==="İZİNDE ÇALIŞTI")).length;

  // ── KİŞİ HAREKET MODALI ─────────────────────────────────────────────────────
  const KisiModal = () => {
    const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();
    const kisiHareketler = hareketler.filter(h => String(h.id)===String(kisiModalId));
    const kisi = kisiHareketler[0] || personeller?.find(p=>String(p.id)===String(kisiModalId));
    const adSoyad = kisi ? `${kisi.ad} ${kisi.soyad}` : "—";

    const shiftGunleri = Object.keys(shiftData)
      .filter(k=>k.startsWith(`${kisiModalId}-`))
      .map(k=>k.replace(`${kisiModalId}-`,""))
      .filter(iso=>iso.match(/^\d{4}-\d{2}-\d{2}$/));

    const tarihToIso = (t) => {
      if(!t) return null;
      if(t.includes("-")) return t;
      const [g,m,y] = t.split("."); return `${y}-${m}-${g}`;
    };

    const tumTarihler = [...new Set([
      ...kisiHareketler.map(h=>tarihToIso(h.tarih)).filter(Boolean),
      ...shiftGunleri
    ])].sort((a,b)=>a>b?-1:1);

    const gunler = ["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"];

    return (
      <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:600}}
        onClick={()=>setKisiModalId(null)}>
        <div style={{background:"var(--card-bg)",border:"1px solid var(--card-border)",borderRadius:12,width:"min(920px,96vw)",maxHeight:"88vh",display:"flex",flexDirection:"column",overflow:"hidden"}}
          onClick={e=>e.stopPropagation()}>

          {/* Header */}
          <div style={{padding:"12px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",alignItems:"center",gap:12,flexShrink:0,background:"#1565A0"}}>
            <div style={{width:38,height:38,borderRadius:"50%",background:"rgba(255,255,255,0.2)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:15,fontWeight:700,color:"#fff",flexShrink:0}}>
              {(kisi?.ad||"?").charAt(0)}
            </div>
            <div style={{flex:1}}>
              <div style={{fontSize:15,fontWeight:700,color:"#fff"}}>{adSoyad}</div>
              <div style={{fontSize:11,color:"rgba(255,255,255,0.65)"}}>{kisi?.departman||""}{kisi?.gorev?` · ${kisi.gorev}`:""}</div>
            </div>
            <div style={{display:"flex",gap:12,fontSize:12,color:"rgba(255,255,255,0.75)"}}>
              <span>{tumTarihler.length} kayıt</span>
              <span style={{color:"#f87171"}}>{kisiHareketler.filter(h=>h.hatali).length} hata</span>
            </div>
            <button onClick={()=>setKisiModalId(null)} style={{background:"rgba(255,255,255,0.15)",border:"none",borderRadius:6,cursor:"pointer",fontSize:16,color:"#fff",width:30,height:30,display:"flex",alignItems:"center",justifyContent:"center"}}>✕</button>
          </div>

          {/* Tablo */}
          <div style={{overflowY:"auto",flex:1}}>
            {tumTarihler.length===0
              ? <div style={{padding:40,textAlign:"center",color:"var(--text-tertiary)",fontSize:13}}>Bu kişiye ait kayıt bulunamadı</div>
              : (
                <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse"}}>
                  <thead>
                    <tr>
                      <th style={{minWidth:90}}>TARİH</th>
                      <th style={{minWidth:55}}>GÜN</th>
                      <th style={{minWidth:130}}>SHIFT</th>
                      <th style={{minWidth:68}}>G.GİRİŞ</th>
                      <th style={{minWidth:68}}>G.ÇIKIŞ</th>
                      <th style={{minWidth:55}}>MESAİ</th>
                      <th>DURUM</th>
                    </tr>
                  </thead>
                  <tbody>
                    {tumTarihler.map(iso => {
                      const [y,m,g]=iso.split("-");
                      const gun=gunler[new Date(iso).getDay()];
                      const tatil=["Cumartesi","Pazar"].includes(gun);
                      const shiftKod=shiftData[`${kisiModalId}-${iso}`]||"";
                      const sObj=[...SHIFTS,...IZINLER].find(s=>s.kod===shiftKod);
                      const har=kisiHareketler.find(h=>tarihToIso(h.tarih)===iso);
                      const hatalar=har?.hatalar||[];
                      const satırBg = hatalar.some(x=>x.tip==="GİRİŞ YOK"||x.tip==="ÇIKIŞ YOK") ? "rgba(163,45,45,0.10)"
                        : hatalar.some(x=>x.tip==="GEÇ GİRİŞ"||x.tip==="ERKEN ÇIKIŞ") ? "rgba(133,79,11,0.08)"
                        : hatalar.some(x=>x.tip==="ERKEN GİRİŞ"||x.tip==="GEÇ ÇIKIŞ") ? "rgba(200,180,0,0.08)"
                        : undefined;
                      const girisHata = har?.hatalar?.some(x=>x.tip.includes("GİRİŞ"));
                      const cikisHata = har?.hatalar?.some(x=>x.tip.includes("ÇIKIŞ"));
                      return (
                        <tr key={iso} style={{background:satırBg}}>
                          <td style={{fontWeight:500,color:tatil?"#A32D2D":"var(--text-primary)"}}>{g}.{m}.{y}</td>
                          <td style={{fontSize:11,color:tatil?"#A32D2D":"var(--text-secondary)",fontWeight:tatil?600:400}}>{gun}</td>
                          <td>{sObj?<span style={{background:sObj.bg,color:sObj.renk,padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:700,whiteSpace:"nowrap"}}>{sObj.kod}{sObj.giris?` (${sObj.giris}-${sObj.cikis})`:""}</span>:<span style={{color:"var(--text-tertiary)",fontSize:11}}>—</span>}</td>
                          <td style={{fontFamily:"monospace",background:girisHata?(har?.hatalar?.some(x=>x.tip==="GİRİŞ YOK")?"rgba(163,45,45,0.12)":"rgba(200,180,0,0.12)"):undefined,color:girisHata?(har?.hatalar?.some(x=>x.tip==="GİRİŞ YOK")?"#A32D2D":"#7A5500"):"var(--text-primary)",fontWeight:girisHata?700:400}}>
                            {har?.gGiris||<span style={{color:shiftKod?"#A32D2D":"var(--text-tertiary)",fontWeight:shiftKod?700:400}}>{shiftKod?"—":"—"}</span>}
                          </td>
                          <td style={{fontFamily:"monospace",background:cikisHata?(har?.hatalar?.some(x=>x.tip==="ÇIKIŞ YOK")?"rgba(163,45,45,0.12)":"rgba(200,180,0,0.12)"):undefined,color:cikisHata?(har?.hatalar?.some(x=>x.tip==="ÇIKIŞ YOK")?"#A32D2D":"#7A5500"):"var(--text-primary)",fontWeight:cikisHata?700:400}}>
                            {har?.gCikis||<span style={{color:shiftKod?"#A32D2D":"var(--text-tertiary)",fontWeight:shiftKod?700:400}}>{shiftKod?"—":"—"}</span>}
                          </td>
                          <td style={{fontFamily:"monospace",fontWeight:har?.mesai&&har.mesai!=="0.00"?700:400,color:har?.mesai&&har.mesai!=="0.00"?"#0F6E56":"var(--text-tertiary)"}}>
                            {har?.mesai&&har.mesai!=="0.00"?har.mesai:"—"}
                          </td>
                          <td>
                            {hatalar.length>0
                              ? hatalar.map((ht,i)=>{const r=hataTipiRenk(ht.tip);return<span key={i} style={{background:r.bg,color:r.c,padding:"2px 6px",borderRadius:4,fontSize:10,fontWeight:700,marginRight:3,display:"inline-block"}}>{ht.tip}</span>;})
                              : har?.gGiris
                                ? <span style={{background:"#EAF3DE",color:"#3B6D11",padding:"2px 6px",borderRadius:4,fontSize:10,fontWeight:600}}>✓ Normal</span>
                                : shiftKod
                                  ? <span style={{background:"#FCEBEB",color:"#A32D2D",padding:"2px 6px",borderRadius:4,fontSize:10}}>Kayıt Yok</span>
                                  : <span style={{color:"var(--text-tertiary)",fontSize:11}}>—</span>
                            }
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              )
            }
          </div>

          {/* Alt bar */}
          <div style={{padding:"8px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",gap:16,alignItems:"center",flexShrink:0,background:"var(--input-bg)",fontSize:12,color:"var(--text-secondary)"}}>
            <span>Toplam: <strong>{tumTarihler.length}</strong></span>
            <span>Hata: <strong style={{color:"#A32D2D"}}>{kisiHareketler.filter(h=>h.hatali).length}</strong></span>
            <span>Mesai: <strong style={{color:"#0F6E56"}}>{kisiHareketler.filter(h=>h.mesai&&h.mesai!=="0.00").length} gün</strong></span>
            <button onClick={()=>setKisiModalId(null)} style={{marginLeft:"auto",padding:"5px 16px",background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:6,cursor:"pointer",fontSize:13,color:"var(--text-primary)",fontFamily:"var(--font-sans)"}}>Kapat</button>
          </div>
        </div>
      </div>
    );
  };

  return (
    <div onClick={()=>ctxMenu&&setCtxMenu(null)} onMouseUp={hMU}
      onKeyDown={e=>{
        if((e.key==="Delete"||e.key==="Backspace") && selCells.size>0 && !editCell) {
          e.preventDefault();
          setHareketler(prev=>{
            const yeni=prev.map(r=>{
              const base=`${r.id}-${r.tarih}`;
              const gSec=selCells.has(`${base}-0`);
              const cSec=selCells.has(`${base}-1`);
              if(!gSec&&!cSec) return r;
              const yeniG=gSec?"":r.gGiris;
              const yeniC=cSec?"":r.gCikis;
              const ss=shiftSaatleri(r.shiftKod);
              const hatalar=hataDetect(r.shiftKod,yeniG,yeniC,r.tarih,BUGUN_TARIH,ss?.girisToler||30);
              return{...r,gGiris:yeniG,gCikis:yeniC,hatalar,hatali:hatalar.length>0};
            });
            saveHareketler(yeni); return yeni;
          });
          setSelCells(new Set());
        }
      }}
      tabIndex={0} style={{outline:"none"}}>

      {kisiModalId && <KisiModal />}

      {ctxMenu && (
        <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:490}} onClick={()=>{setCtxMenu(null);setCtxSubMenu(null);}} />
      )}
      {ctxMenu && (() => {
        const h = ctxMenu.h;
        const menuBtn = (label, icon, fn, color) => (
          <button onClick={(e)=>{e.stopPropagation();fn();}} onMouseEnter={e=>{e.currentTarget.style.background="var(--input-bg)";setCtxSubMenu(null);}} onMouseLeave={e=>e.currentTarget.style.background=""}
            style={{width:"100%",padding:"8px 14px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,color:color||"var(--text-primary)",display:"flex",alignItems:"center",gap:10,fontFamily:"var(--font-sans)"}}>
            {icon&&<span style={{fontSize:12}}>{icon}</span>}<span style={{flex:1}}>{label}</span>
          </button>
        );
        const subMenuBtn = (key, label, icon) => (
          <button onMouseEnter={e=>{e.currentTarget.style.background="var(--input-bg)";setCtxSubMenu(key);}} onMouseLeave={e=>e.currentTarget.style.background=""}
            style={{width:"100%",padding:"8px 14px",border:"none",background:ctxSubMenu===key?"var(--input-bg)":"none",cursor:"pointer",textAlign:"left",fontSize:13,color:"var(--text-primary)",display:"flex",alignItems:"center",gap:10,fontFamily:"var(--font-sans)"}}>
            {icon&&<span>{icon}</span>}<span style={{flex:1}}>{label}</span><span style={{color:"var(--text-tertiary)",fontSize:11}}>▶</span>
          </button>
        );
        const sep = () => <div style={{height:1,background:"var(--grid-line)",margin:"2px 0"}} />;
        return (
          <div style={{position:"fixed",top:ctxMenu.y,left:ctxMenu.x,background:"var(--card-bg)",border:"1px solid var(--input-border)",borderRadius:8,zIndex:500,minWidth:260,boxShadow:"0 8px 24px rgba(0,0,0,.4)",overflow:"visible"}} onClick={e=>e.stopPropagation()}>
            <div style={{padding:"7px 14px",fontSize:11,color:"var(--text-tertiary)",borderBottom:"1px solid var(--grid-line)",fontWeight:600,background:"var(--input-bg)",borderRadius:"8px 8px 0 0"}}>
              {selCells.size > 1
                ? <span style={{color:"#185FA5"}}>{selCells.size} hücre seçili</span>
                : <>{h.ad} {h.soyad} · {h.tarih}
                  <span style={{marginLeft:8,background:shiftObj(h.shiftKod).bg,color:shiftObj(h.shiftKod).renk,padding:"1px 6px",borderRadius:4,fontSize:10,fontWeight:700}}>{h.shiftKod}</span>
                </>
              }
            </div>
            {selCells.size > 1 && (<>
              {menuBtn("Seçilenleri Shifte Göre Doldur","⚡",()=>{
                const saatEkleL=(saat,dk)=>{if(!saat)return"";const[hr,mn]=saat.split(":").map(Number);const t=hr*60+mn+dk;const yH=Math.floor(((t%1440)+1440)%1440/60);const yM=((t%1440)+1440)%1440%60;return`${String(yH).padStart(2,"0")}:${String(yM).padStart(2,"0")}`;};
                const rastL=(hedef,muf)=>{if(!hedef)return"";const dk=Math.floor(Math.random()*(muf+1));return saatEkleL(hedef,Math.random()>0.3?-dk:dk);};
                setHareketler(prev=>{
                  let yeni=[...prev];
                  sortedFiltered.forEach(r=>{
                    const base=`${r.id}-${r.tarih}`;
                    const gSecili=selCells.has(`${base}-0`);
                    const cSecili=selCells.has(`${base}-1`);
                    if(!gSecili&&!cSecili) return;
                    const s=shiftObj(r.shiftKod); if(!s.giris) return;
                    const yeniG=gSecili?(r.gGiris||rastL(s.giris,s.muafiyet||30)):r.gGiris;
                    const yeniC=cSecili?(r.gCikis||rastL(s.cikis,s.cikisMuafiyet||30)):r.gCikis;
                    const ss=shiftSaatleri(r.shiftKod);
                    const hatalar=hataDetect(r.shiftKod,yeniG,yeniC,r.tarih,BUGUN_TARIH,ss?.girisToler||30);
                    const g={...r,gGiris:yeniG,gCikis:yeniC,hatalar,hatali:hatalar.length>0,_hayalet:false};
                    const idx=yeni.findIndex(x=>String(x.id)===String(r.id)&&x.tarih===r.tarih);
                    if(idx>=0) yeni[idx]=g; else yeni.push(g);
                  });
                  saveHareketler(yeni); return yeni;
                });
                setSelCells(new Set()); setCtxMenu(null);
              },"#0F6E56")}
              {menuBtn("Seçilenleri Temizle","🗑️",()=>{
                setHareketler(prev=>{
                  const yeni=prev.map(r=>{
                    const base=`${r.id}-${r.tarih}`;
                    const gSecili=selCells.has(`${base}-0`);
                    const cSecili=selCells.has(`${base}-1`);
                    if(!gSecili&&!cSecili) return r;
                    const yeniG=gSecili?"":r.gGiris;
                    const yeniC=cSecili?"":r.gCikis;
                    const ss=shiftSaatleri(r.shiftKod);
                    const hatalar=hataDetect(r.shiftKod,yeniG,yeniC,r.tarih,BUGUN_TARIH,ss?.girisToler||30);
                    return{...r,gGiris:yeniG,gCikis:yeniC,hatalar,hatali:hatalar.length>0};
                  });
                  saveHareketler(yeni); return yeni;
                });
                setSelCells(new Set()); setCtxMenu(null);
              },"#A32D2D")}
              {sep()}
            </>)}
            {menuBtn("Hareketi Sil","🗑️",()=>{if(!confirm(`${h.ad} ${h.soyad} - ${h.tarih} silinsin mi?`))return;guncelleHareket(h.id,h.tarih,"gGiris","");guncelleHareket(h.id,h.tarih,"gCikis","");setCtxMenu(null);},"#A32D2D")}
            {sep()}
            <div style={{position:"relative"}}>
              {subMenuBtn("shift","Shift Değiştir","🔄")}
              {ctxSubMenu==="shift"&&(
                <div style={{position:"absolute",left:ctxMenu.x+480>window.innerWidth?"-200px":"100%",top:0,background:"var(--card-bg)",border:"1px solid var(--input-border)",borderRadius:8,zIndex:501,minWidth:200,boxShadow:"0 8px 24px rgba(0,0,0,.4)",overflow:"hidden"}}>
                  {siralanmisShifts(SHIFTS).filter(s=>s.kullanimda!==false).map(s=>(
                    <button key={s.kod} onClick={()=>{guncelleHareket(h.id,h.tarih,"shiftKod",s.kod);setCtxMenu(null);setCtxSubMenu(null);}}
                      onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"} onMouseLeave={e=>e.currentTarget.style.background=""}
                      style={{width:"100%",padding:"7px 12px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,display:"flex",alignItems:"center",gap:8,fontFamily:"var(--font-sans)"}}>
                      <span style={{background:s.bg,color:s.renk,padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:700,minWidth:36,textAlign:"center"}}>{s.kod}</span>
                      <span style={{flex:1,fontSize:12}}>{s.ad}</span>
                      {s.giris&&<span style={{fontSize:10,color:"var(--text-tertiary)"}}>{s.giris}-{s.cikis}</span>}
                    </button>
                  ))}
                </div>
              )}
            </div>
            <div style={{position:"relative"}}>
              {subMenuBtn("izin","İzin Değiştir","📋")}
              {ctxSubMenu==="izin"&&(
                <div style={{position:"absolute",left:ctxMenu.x+480>window.innerWidth?"-200px":"100%",top:0,background:"var(--card-bg)",border:"1px solid var(--input-border)",borderRadius:8,zIndex:501,minWidth:200,boxShadow:"0 8px 24px rgba(0,0,0,.4)",overflow:"hidden",maxHeight:400,overflowY:"auto"}}>
                  <div style={{padding:"5px 12px",fontSize:10,fontWeight:700,color:"#185FA5",background:"#E6F1FB"}}>✅ Ücretli İzinler</div>
                  {IZINLER.filter(s=>s.tip!=="ucretsiz").map(s=>(<button key={s.kod} onClick={()=>{guncelleHareket(h.id,h.tarih,"shiftKod",s.kod);setCtxMenu(null);setCtxSubMenu(null);}} onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"} onMouseLeave={e=>e.currentTarget.style.background=""} style={{width:"100%",padding:"7px 12px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,display:"flex",alignItems:"center",gap:8,fontFamily:"var(--font-sans)"}}><span style={{background:s.bg,color:s.renk,padding:"2px 6px",borderRadius:4,fontSize:11,fontWeight:700,minWidth:28,textAlign:"center"}}>{s.kod}</span><span style={{fontSize:12}}>{s.ad}</span></button>))}
                  <div style={{padding:"5px 12px",fontSize:10,fontWeight:700,color:"#A32D2D",background:"#FCEBEB"}}>❌ Ücretsiz İzinler</div>
                  {IZINLER.filter(s=>s.tip==="ucretsiz").map(s=>(<button key={s.kod} onClick={()=>{guncelleHareket(h.id,h.tarih,"shiftKod",s.kod);setCtxMenu(null);setCtxSubMenu(null);}} onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"} onMouseLeave={e=>e.currentTarget.style.background=""} style={{width:"100%",padding:"7px 12px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,display:"flex",alignItems:"center",gap:8,fontFamily:"var(--font-sans)"}}><span style={{background:s.bg,color:s.renk,padding:"2px 6px",borderRadius:4,fontSize:11,fontWeight:700,minWidth:28,textAlign:"center"}}>{s.kod}</span><span style={{fontSize:12}}>{s.ad}</span></button>))}
                </div>
              )}
            </div>
            {sep()}
            {menuBtn("Giriş Saatini Düzenle","⏰",()=>{setEditCell({id:h.id,tarih:h.tarih,field:"gGiris"});setEditVal(h.gGiris||"");setCtxMenu(null);})}
            {menuBtn("Çıkış Saatini Düzenle","⏰",()=>{setEditCell({id:h.id,tarih:h.tarih,field:"gCikis"});setEditVal(h.gCikis||"");setCtxMenu(null);})}
            {sep()}
            {menuBtn("Bu Kaydı Shifte Göre Doldur","🎲",()=>{
              const s = shiftObj(h.shiftKod);
              if(!s.giris) { alert("Bu shift için saat tanımlanmamış."); setCtxMenu(null); return; }
              const saatEkleL=(saat,dk)=>{if(!saat)return"";const[hr,mn]=saat.split(":").map(Number);const t=hr*60+mn+dk;const yH=Math.floor(((t%1440)+1440)%1440/60);const yM=((t%1440)+1440)%1440%60;return`${String(yH).padStart(2,"0")}:${String(yM).padStart(2,"0")}`;};
              const rastL=(hedef,muf)=>{if(!hedef)return"";const dk=Math.floor(Math.random()*(muf+1));return saatEkleL(hedef,Math.random()>0.3?-dk:dk);};
              const muf=s.muafiyet||30, cmuf=s.cikisMuafiyet||30;
              const yeniG=h.gGiris||rastL(s.giris,muf);
              const yeniC=h.gCikis||rastL(s.cikis,cmuf);
              const ss=shiftSaatleri(h.shiftKod);
              const hatalar=hataDetect(h.shiftKod,yeniG,yeniC,h.tarih,BUGUN_TARIH,ss?.girisToler||30);
              const kayitGuncellendi = {
                ...h, gGiris:yeniG, gCikis:yeniC,
                hatalar, hatali:hatalar.length>0,
                _hayalet:false
              };
              setHareketler(prev => {
                // Kayıt zaten varsa güncelle, yoksa (hayalet) ekle
                const varMi = prev.some(r=>String(r.id)===String(h.id)&&r.tarih===h.tarih);
                const yeni = varMi
                  ? prev.map(r=>String(r.id)===String(h.id)&&r.tarih===h.tarih ? kayitGuncellendi : r)
                  : [...prev, kayitGuncellendi];
                saveHareketler(yeni); return yeni;
              });
              setCtxMenu(null);
            },"#185FA5")}
            {menuBtn("Tüm Filtrelileri Shifte Göre Doldur","⚡",()=>{
              if(!confirm(`${filtered.length} kayıt shifte göre doldurulacak (boş olanlar). Devam?`)) return;
              const saatEkleL=(saat,dk)=>{if(!saat)return"";const[hr,mn]=saat.split(":").map(Number);const t=hr*60+mn+dk;const yH=Math.floor(((t%1440)+1440)%1440/60);const yM=((t%1440)+1440)%1440%60;return`${String(yH).padStart(2,"0")}:${String(yM).padStart(2,"0")}`;};
              const rastL=(hedef,muf)=>{if(!hedef)return"";const dk=Math.floor(Math.random()*(muf+1));return saatEkleL(hedef,Math.random()>0.3?-dk:dk);};
              setHareketler(prev => {
                // Önce mevcut kayıtları güncelle
                const mevcutGuncellendi = prev.map(r => {
                  const varMi = filtered.some(f=>!f._hayalet&&String(f.id)===String(r.id)&&f.tarih===r.tarih);
                  if(!varMi) return r;
                  const s=shiftObj(r.shiftKod); if(!s.giris) return r;
                  const muf=s.muafiyet||30,cmuf=s.cikisMuafiyet||30;
                  const yeniG=r.gGiris||rastL(s.giris,muf);
                  const yeniC=r.gCikis||rastL(s.cikis,cmuf);
                  const ss=shiftSaatleri(r.shiftKod);
                  const hatalar=hataDetect(r.shiftKod,yeniG,yeniC,r.tarih,BUGUN_TARIH,ss?.girisToler||30);
                  return{...r,gGiris:yeniG,gCikis:yeniC,hatalar,hatali:hatalar.length>0};
                });
                // Sonra hayalet satırları (shift var, hareketler'de yok) ekle
                const hayaletler = filtered.filter(f=>f._hayalet);
                const yeniHayaletler = hayaletler.map(h => {
                  const s=shiftObj(h.shiftKod); if(!s.giris) return null;
                  const muf=s.muafiyet||30,cmuf=s.cikisMuafiyet||30;
                  const yeniG=rastL(s.giris,muf);
                  const yeniC=rastL(s.cikis,cmuf);
                  const ss=shiftSaatleri(h.shiftKod);
                  const hatalar=hataDetect(h.shiftKod,yeniG,yeniC,h.tarih,BUGUN_TARIH,ss?.girisToler||30);
                  return{...h,gGiris:yeniG,gCikis:yeniC,hatalar,hatali:hatalar.length>0,_hayalet:false};
                }).filter(Boolean);
                const yeni = [...mevcutGuncellendi, ...yeniHayaletler];
                saveHareketler(yeni); return yeni;
              });
              setCtxMenu(null);
            },"#0F6E56")}
            {h.hatali&&(<div style={{borderTop:"1px solid var(--grid-line)",padding:"6px 12px"}}>{h.hatalar?.map((ht,i)=>{const r=hataTipiRenk(ht.tip);return<div key={i} style={{background:r.bg,color:r.c,padding:"3px 8px",borderRadius:4,fontSize:11,fontWeight:600,marginBottom:2}}>{ht.tip}: <span style={{fontWeight:400}}>{ht.aciklama}</span></div>;})}</div>)}
          </div>
        );
      })()}

      {/* ── TOOLBAR ─────────────────────────────────────────────────────────── */}
      <div style={{display:"flex",gap:6,marginBottom:10,alignItems:"center",flexWrap:"wrap"}}>
        {/* Departman */}
        <Select value={dept} onChange={e=>{setDept(e.target.value);setSeciliPersonelId("TÜMÜ");}} style={{width:175,flexShrink:0}}>
          <option value="TÜMÜ">-TÜM DEPARTMANLAR-</option>
          {getDepartmanlar().map(d=><option key={d.ad} value={d.ad}>{d.ad}</option>)}
        </Select>
        {/* Personel seçimi */}
        <Select value={seciliPersonelId} onChange={e=>setSeciliPersonelId(e.target.value)} style={{width:175,flexShrink:0}}>
          <option value="TÜMÜ">-TÜM PERSONELLER-</option>
          {personelSecenekleri.map(p=><option key={p.id} value={String(p.id)}>{p.ad} {p.soyad}</option>)}
        </Select>
        {/* Tarih — uncontrolled, sadece blur'da state güncellenir */}
        <input type="date" defaultValue={basTarih}
          onBlur={e=>e.target.value&&setBasTarih(e.target.value)}
          onChange={e=>{ if(e.target.value?.length===10) setBasTarih(e.target.value); }}
          style={inputStyle} />
        <span style={{fontSize:12,color:"var(--text-secondary)"}}>—</span>
        <input type="date" defaultValue={bitTarih}
          onBlur={e=>e.target.value&&setBitTarih(e.target.value)}
          onChange={e=>{ if(e.target.value?.length===10) setBitTarih(e.target.value); }}
          style={inputStyle} />
        <Btn onClick={()=>{setBasTarih(BUGUN_ISO);setBitTarih(BUGUN_ISO);setListeParams({bas:BUGUN_ISO,bit:BUGUN_ISO,dept,pid:seciliPersonelId});}}>Bugün</Btn>
        <Btn onClick={()=>{
          const d=new Date(BUGUN_ISO);const day=d.getDay();const diff=day===0?-6:1-day;
          d.setDate(d.getDate()+diff);const bas=d.toISOString().slice(0,10);
          const bit=new Date(d);bit.setDate(bit.getDate()+6);const bitS=bit.toISOString().slice(0,10);
          setBasTarih(bas);setBitTarih(bitS);
          setListeParams({bas,bit:bitS,dept,pid:seciliPersonelId});
        }}>Bu Hafta</Btn>

        <div style={{width:1,height:22,background:"var(--grid-line)",margin:"0 2px",flexShrink:0}} />

        {/* Sol dropdown: Shift veya İzin seçimi */}
        <Select value={shiftFiltre} onChange={e=>setShiftFiltre(e.target.value)} style={{width:160,flexShrink:0}}>
          <option value="TÜMÜ">-TÜM HAREKETLER-</option>
          <optgroup label="── Shiftler ──">
            <option value="TUM_SHIFTLER">-TÜM SHİFTLER-</option>
            {siralanmisShifts(SHIFTS).filter(s=>s.kullanimda!==false).map(s=>(
              <option key={s.kod} value={s.kod}>{s.kod}{s.giris?`-${s.giris} ${s.cikis}`:""}</option>
            ))}
          </optgroup>
          <optgroup label="── İzinler ──">
            <option value="TUM_IZINLER">-TÜM İZİNLER-</option>
            {IZINLER.map(s=><option key={s.kod} value={s.kod}>{s.ad}</option>)}
          </optgroup>
        </Select>

        {/* Sağ dropdown: Hata/özel filtre */}
        <Select value={hataFiltre} onChange={e=>setHataFiltre(e.target.value)} style={{width:185,flexShrink:0}}>
          <option value="TÜMÜ">-TÜM HAREKETLER-</option>
          <option value="MESAI_GIRILENLER">MESAİ GİRİLENLER</option>
          <option value="OKUTMA_UNUTANLAR">OKUTMA UNUTANLAR</option>
          <option value="OKUTMA_UNUTANLAR_ANT">OKUTMA UNUTANLAR (ANT)</option>
          <option value="SHIFTE_UYMAYANLAR">SHİFTE UYMAYANLAR</option>
          <option value="TUM_HATALI">TÜM HATALI HAREKETLER</option>
          <option value="SHIFT_ATANMAYANLAR">SHİFT ATANMAYANLAR</option>
        </Select>

        <div style={{width:1,height:22,background:"var(--grid-line)",margin:"0 2px",flexShrink:0}} />

        <Btn primary onClick={handleListele}><span style={{fontSize:15}}>📋</span><span>Listele [F2]</span></Btn>
        <Btn><span style={{fontSize:15}}>🖨️</span><span>Yazdır</span></Btn>
        <Btn onClick={hesaplaMesai}><span style={{fontSize:15}}>⏱️</span><span>Mesai Hesapla</span></Btn>

        {/* Mesai Sıfırla */}
        {(()=>{
          const [ac,setAc]=React.useState(false);
          const filtrele=(h)=>{const t=trToNum(h.tarih);return t>=basNum&&t<=bitNum&&(dept==="TÜMÜ"||h.departman===dept)&&(seciliPersonelId==="TÜMÜ"||String(h.id)===String(seciliPersonelId));};
          return(
            <div style={{position:"relative"}}>
              <Btn danger onClick={()=>setAc(v=>!v)}><span style={{fontSize:15}}>✕</span><span>Mesai Sıfırla ▾</span></Btn>
              {ac&&(
                <div style={{position:"absolute",top:"100%",left:0,marginTop:4,background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:8,boxShadow:"0 4px 16px rgba(0,0,0,.2)",zIndex:200,minWidth:220,overflow:"hidden"}}>
                  <button onClick={()=>{setAc(false);setHareketler(prev=>{const y=prev.map(h=>filtrele(h)&&!h.mesaiManuel?{...h,mesai:"0.00",mesaiAuto:false}:h);saveHareketler(y);return y;});}}
                    style={{width:"100%",padding:"10px 14px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,fontFamily:"var(--font-sans)",display:"flex",flexDirection:"column",gap:2}}
                    onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"} onMouseLeave={e=>e.currentTarget.style.background="none"}>
                    <span style={{fontWeight:600}}>🤖 Otomatik Hesaplananları Sil</span>
                    <span style={{fontSize:11,color:"var(--text-tertiary)"}}>Elle girilen mesailer korunur</span>
                  </button>
                  <div style={{borderTop:"1px solid var(--grid-line)"}}/>
                  <button onClick={()=>{if(!confirm("Elle girilenler dahil tümü sıfırlanacak?"))return;setAc(false);setHareketler(prev=>{const y=prev.map(h=>filtrele(h)?{...h,mesai:"0.00",mesaiAuto:false,mesaiManuel:false}:h);saveHareketler(y);return y;});}}
                    style={{width:"100%",padding:"10px 14px",border:"none",background:"none",cursor:"pointer",textAlign:"left",fontSize:13,color:"#A32D2D",fontFamily:"var(--font-sans)",display:"flex",flexDirection:"column",gap:2}}
                    onMouseEnter={e=>e.currentTarget.style.background="#FCEBEB"} onMouseLeave={e=>e.currentTarget.style.background="none"}>
                    <span style={{fontWeight:600}}>🗑️ Hepsini Sil</span>
                    <span style={{fontSize:11,color:"#A32D2D99"}}>Elle girilenleri de sıfırlar</span>
                  </button>
                </div>
              )}
            </div>
          );
        })()}

        {/* Excel */}
        <Btn style={{marginLeft:"auto"}} onClick={()=>{
          const rows=sortedFiltered.map(h=>({"ADI":h.ad,"SOYADI":h.soyad,"DEPARTMAN":h.departman,"GÖREV":h.gorev,"TARİH":h.tarih,"SHIFT":h.shiftKod,"G.GİRİŞ":h.gGiris||"","G.ÇIKIŞ":h.gCikis||"","MESAİ":h.mesai||"","HATA":h.hatalar?.map(x=>x.tip).join(", ")||""}));
          exportToExcel(rows, ["ADI","SOYADI","DEPARTMAN","GÖREV","TARİH","SHIFT","G.GİRİŞ","G.ÇIKIŞ","MESAİ","HATA"], `giris_cikis_${new Date().toLocaleDateString("tr-TR")}.xlsx`);
        }}><span style={{fontSize:15}}>📥</span><span>Excel</span></Btn>
      </div>

      {/* ── ÖZET BANT ────────────────────────────────────────────────────────── */}
      {(girisYok+cikisYok+gecGiris+erkenGiris+erkenCikis+gecCikis+izindeCalisti) > 0 && (
        <div style={{display:"flex",gap:6,flexWrap:"wrap",marginBottom:8}}>
          {[
            ["GİRİŞ YOK",girisYok,"#FCEBEB","#A32D2D","OKUTMA_UNUTANLAR"],
            ["ÇIKIŞ YOK",cikisYok,"#FCEBEB","#A32D2D","OKUTMA_UNUTANLAR_ANT"],
            ["GEÇ GİRİŞ",gecGiris,"#FAEEDA","#854F0B","SHIFTE_UYMAYANLAR"],
            ["ERKEN GİRİŞ",erkenGiris,"#FFF3CD","#7A5500","SHIFTE_UYMAYANLAR"],
            ["ERKEN ÇIKIŞ",erkenCikis,"#FAEEDA","#854F0B","SHIFTE_UYMAYANLAR"],
            ["GEÇ ÇIKIŞ",gecCikis,"#FFF3CD","#7A5500","SHIFTE_UYMAYANLAR"],
            ["İZİNDE ÇALIŞTI",izindeCalisti,"#F3E8FF","#6B21A8","IZINDE_CALISTI"],
          ].filter(([,n])=>n>0).map(([lbl,n,bg,c,filtre])=>(
            <span key={lbl}
              onClick={()=>setHataFiltre(prev=>prev===filtre?"TÜMÜ":filtre)}
              style={{background:bg,color:c,padding:"4px 12px",borderRadius:20,fontSize:11,fontWeight:700,
                display:"inline-flex",alignItems:"center",gap:6,cursor:"pointer",
                outline:hataFiltre===filtre?`2px solid ${c}`:"none",outlineOffset:2}}>
              {lbl} <span style={{background:"rgba(0,0,0,0.12)",borderRadius:10,padding:"0 6px"}}>{n}</span>
            </span>
          ))}
          <span style={{marginLeft:"auto",fontSize:11,color:"var(--text-tertiary)",alignSelf:"center"}}>
            {filtered.length} kayıt · {hatalilar.length} hatalı
          </span>
        </div>
      )}

      {/* ── TABLO ─────────────────────────────────────────────────────────────── */}
      {selCells.size > 0 && (
        <div style={{display:"flex",gap:8,alignItems:"center",marginBottom:6,padding:"5px 12px",background:"#E6F1FB",border:"1px solid #185FA5",borderRadius:8,fontSize:12}}>
          <span style={{color:"#185FA5",fontWeight:600}}>{selCells.size} hücre seçili</span>
          <span style={{color:"var(--text-tertiary)",fontSize:11}}>— sağ tıklayarak işlem yapın</span>
          <button onClick={()=>setSelCells(new Set())} style={{marginLeft:"auto",padding:"2px 8px",background:"none",color:"#185FA5",border:"none",cursor:"pointer",fontSize:12,fontFamily:"var(--font-sans)"}}>✕</button>
        </div>
      )}
      <div className="pdks-card">
        <div style={{padding:"8px 14px",userSelect:"none"}}>
          <DraggableTable cols={cols} setCols={setCols} hiddenCols={hiddenCols} setHiddenCols={setHiddenCols} onSortChange={s=>setSortState(s)}>
            <tbody>
              {sortedFiltered.map((h, rowIdx)=>{
                const base = `${h.id}-${h.tarih}`;
                const g0 = `${base}-0`; // giriş key
                const g1 = `${base}-1`; // çıkış key
                const gSel = selCells.has(g0);
                const cSel = selCells.has(g1);
                const isOff = h.shiftKod==="OFF" || IZIN_KODLARI.has(h.shiftKod);
                return (
                  <tr key={base} style={{background:(gSel||cSel)?"rgba(21,101,160,0.08)":satirRenk(h)}}
                    onContextMenu={e=>{
                      e.preventDefault();
                      const menuW=260,menuH=500;
                      const x=Math.min(e.clientX,window.innerWidth-menuW-8);
                      const y=Math.min(e.clientY,window.innerHeight-menuH-8);
                      setCtxMenu({x,y,h}); setCtxSubMenu(null);
                    }}>
                    {cols.filter(c=>!hiddenCols.has(c)).map(col=>{
                      const isG=col==="G.GİRİŞ", isC=col==="G.ÇIKIŞ";
                      if(!isG&&!isC) return <td key={col}>{cellVal(h,col)}</td>;
                      const di = isG?0:1;
                      const field = isG?"gGiris":"gCikis";
                      const val = isG?h.gGiris:h.gCikis;
                      const isSel = isG?gSel:cSel;
                      const isEdit = editCell?.id===h.id&&editCell?.tarih===h.tarih&&editCell?.field===field;
                      const hErr = !isOff&&h.hatalar?.some(x=>x.tip.includes(isG?"GİRİŞ":"ÇIKIŞ"));
                      const hRed = !isOff&&h.hatalar?.some(x=>x.tip===(isG?"GİRİŞ YOK":"ÇIKIŞ YOK"));
                      if(isEdit) return (
                        <td key={col} style={{padding:"2px 4px"}}>
                          <input type="time" value={editVal} autoFocus
                            onChange={e=>setEditVal(e.target.value)}
                            onBlur={e=>{ if(e.target.value) guncelleHareket(h.id,h.tarih,field,e.target.value,editCell?.hayalet||h); setEditCell(null); }}
                            onKeyDown={e=>{
                              if(e.key==="Enter") { if(editVal) guncelleHareket(h.id,h.tarih,field,editVal,editCell?.hayalet||h); setEditCell(null); }
                              if(e.key==="Escape") setEditCell(null);
                            }}
                            style={{width:72,padding:"2px 4px",border:"2px solid #1565A0",borderRadius:4,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:12,fontFamily:"monospace"}}
                          />
                        </td>
                      );
                      return (
                        <td key={col}
                          style={{
                            cursor:"crosshair",
                            outline:isSel?"2px solid #60a5fa":"none",
                            outlineOffset:"-2px",
                            background:isSel?"rgba(21,101,160,0.25)":(hRed?"rgba(163,45,45,0.10)":hErr?"rgba(200,180,0,0.08)":"transparent"),
                            fontFamily:"monospace", fontSize:12,
                            fontWeight:hErr?700:400,
                            color:hRed?"#A32D2D":hErr?"#7A5500":val?"var(--text-primary)":"var(--text-tertiary)",
                            minWidth:60, padding:"4px 8px",
                            userSelect:"none",
                          }}
                          onMouseDown={e=>{ if(e.target.closest("input")) return; hMD(rowIdx,di,e); }}
                          onMouseEnter={()=>hME(rowIdx,di)}
                          onMouseUp={()=>{
                            hMU();
                            if(dragStart.current?.pi===rowIdx && dragStart.current?.di===di) {
                              setEditCell({id:h.id, tarih:h.tarih, field, hayalet:h._hayalet?h:null});
                              setEditVal(val||"");
                              setSelCells(new Set());
                            }
                          }}>
                          {val||"—"}
                        </td>
                      );
                    })}
                  </tr>
                );
              })}
              {sortedFiltered.length===0&&(
                <tr><td colSpan={cols.length} style={{padding:24,textAlign:"center",color:"var(--text-tertiary)"}}>Bu tarih aralığında kayıt yok</td></tr>
              )}
            </tbody>
          </DraggableTable>
        </div>
      </div>

      {/* Alt özet */}
      <div style={{marginTop:8,fontSize:11,color:"var(--text-tertiary)",display:"flex",gap:16}}>
        <span>Listelenen Kayıt: <strong>{sortedFiltered.length}</strong></span>
        {hatalilar.length>0&&<span style={{color:"#A32D2D"}}>Hatalı: <strong>{hatalilar.length}</strong></span>}
      </div>
    </div>
  );
};

// ─── HATALΙ SHIFT HAREKETLER ─────────────────────────────────────────────────
const HataliHareketler = ({aciklamaGizle, setAciklamaGizle, hiddenColsExt, setHiddenColsExt, uid="guest", personeller=[], kullanici=null}) => {
  const [mod, setMod] = useState("bugun");
  const [basTarih, setBasTarih] = useState(BUGUN_ISO);
  const [bitTarih, setBitTarih] = useState(BUGUN_ISO);

  const COLS_BASE = ["DEPARTMAN","GÖREV","PERSONEL","TARİH","SHIFT","G.GİRİŞ","G.ÇIKIŞ","HATA TÜRÜ","AÇIKLAMA"];
  // Sütun sırası kalıcı, hiddenCols App'ten geliyor (aciklamaGizle ile bağlı)
  const [cols, setCols] = usePersistentCols(uid, "hatali_col_order", COLS_BASE);
  const hiddenCols = hiddenColsExt;
  const setHiddenCols = setHiddenColsExt;
  const [sortState, setSortState] = useState({col:null,dir:0});

  // aciklamaGizle değişince hiddenCols'u güncelle
  const handleAciklamaGizle = (val) => {
    setAciklamaGizle(val);
    setHiddenCols(prev => {
      const n = new Set(prev);
      val ? n.add("AÇIKLAMA") : n.delete("AÇIKLAMA");
      return n;
    });
  };

  // İlk render'da aciklamaGizle state'ini hiddenCols ile senkronize et
  useEffect(() => {
    setHiddenCols(prev => {
      const n = new Set(prev);
      aciklamaGizle ? n.add("AÇIKLAMA") : n.delete("AÇIKLAMA");
      return n;
    });
  // eslint-disable-next-line
  }, []);

  const getAralik = () => {
    if(mod==="bugun") return {bas:BUGUN_TARIH, bit:BUGUN_TARIH};
    if(mod==="hafta") return {bas:haftaPazartesi(BUGUN_TARIH), bit:BUGUN_TARIH};
    const cvt = s => { const [y,m,g]=s.split("-"); return `${g}.${m}.${y}`; };
    return {bas:cvt(basTarih), bit:cvt(bitTarih)};
  };

  const aralik = getAralik();

  // Kullanıcının erişebileceği departmanlar
  const izinliDeptler = kullanici?.yetki==="admin"
    ? null // admin = hepsi
    : (kullanici?.departmanlar || []);

  const hareketlerLS = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):[]; } catch{return[];} })();
  // Hata hesaplamalarını memoize et — sadece localStorage değişince yeniden hesapla
  const tumHareketler = React.useMemo(() =>
    (hareketlerLS.length > 0 ? hareketlerLS : TUM_HAREKETLER).map(h => {
      const ss = shiftSaatleri(h.shiftKod);
      const girisToler = ss?.girisToler || 30;
      const hatalar = hataDetect(h.shiftKod, h.gGiris, h.gCikis, h.tarih, BUGUN_TARIH, girisToler);
      return {...h, hatalar, hatali: hatalar.length > 0};
    })
  , [hareketlerLS.length]); // length değişince yeniden hesapla

  const hatalilar = tumHareketler.filter(h => {
    if(!h.hatali && !h.hatalar?.length) return false;
    if(izinliDeptler && !izinliDeptler.includes(h.departman)) return false;
    const diff1 = tarihKarsilastir(h.tarih, aralik.bas);
    const diff2 = tarihKarsilastir(h.tarih, aralik.bit);
    if(diff1 < 0 || diff2 > 0) return false;

    const mesaiVar = h.mesai && h.mesai !== "0.00";
    const hataTipleri = (h.hatalar||[]).map(x=>x.tip);

    // Mesai girilmişse sadece ciddi hatalar kalsın
    if(mesaiVar) {
      return hataTipleri.some(t =>
        t==="GİRİŞ YOK" || t==="ÇIKIŞ YOK" ||
        t==="ERKEN ÇIKIŞ" || t==="İZİNDE ÇALIŞTI"
      );
    }

    // Mesai yoksa tüm hataları göster
    return hataTipleri.length > 0;
  });

  const inputStyle = {padding:"7px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",fontFamily:"var(--font-sans)"};

  const hataTipiStyle = (tip) => {
    if(tip==="ERKEN GİRİŞ") return {background:"#FAEEDA",color:"#854F0B"};
    if(tip==="GEÇ GİRİŞ")  return {background:"#FAEEDA",color:"#854F0B"};
    if(tip==="ÇIKIŞ YOK")  return {background:"#FCEBEB",color:"#A32D2D"};
    if(tip==="GİRİŞ YOK")  return {background:"#FCEBEB",color:"#A32D2D"};
    return {background:"#F1EFE8",color:"#5F5E5A"};
  };

  const cellVal = (h, hata, col) => {
    const s = shiftObj(h.shiftKod);
    switch(col) {
      case "DEPARTMAN": return <span style={{color:"var(--text-secondary)"}}>{h.departman}</span>;
      case "GÖREV":     return <span style={{color:"var(--text-secondary)"}}>{h.gorev}</span>;
      case "PERSONEL":  return <span style={{fontWeight:600}}>{h.ad} {h.soyad}</span>;
      case "TARİH":     return h.tarih;
      case "SHIFT":     return <span style={{background:s.bg,color:s.renk,padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:600,whiteSpace:"nowrap"}}>{h.shiftKod}{s.saat?" ("+s.saat+")":""}</span>;
      case "G.GİRİŞ":   return <span style={{fontWeight:500}}>{h.gGiris||"—"}</span>;
      case "G.ÇIKIŞ":   return h.gCikis ? <span style={{fontWeight:500}}>{h.gCikis}</span> : <span style={{background:"#FCEBEB",color:"#A32D2D",fontWeight:600,padding:"2px 8px",borderRadius:4,fontSize:11}}>—</span>;
      case "HATA TÜRÜ": return <span style={{...hataTipiStyle(hata.tip),padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:600,whiteSpace:"nowrap"}}>{hata.tip}</span>;
      case "AÇIKLAMA":  return <span style={{color:"var(--text-secondary)",fontSize:11}}>{hata.aciklama}</span>;
      default: return "—";
    }
  };

  const visibleCols = cols.filter(c=>!hiddenCols.has(c));

  const toDateNum = (t) => { if(!t) return 0; const p=t.includes("-")?t.split("-"):t.split(".").reverse(); return parseInt(p.join(""))||0; };
  const sortedHatalilar = (() => {
    const {col,dir} = sortState;
    if(!col||dir===0) return hatalilar;
    return [...hatalilar].sort((a,b)=>{
      if(col==="TARİH") { const c=toDateNum(a.tarih)-toDateNum(b.tarih); return dir===1?c:-c; }
      const km={"DEPARTMAN":"departman","GÖREV":"gorev","PERSONEL":"ad","G.GİRİŞ":"gGiris","G.ÇIKIŞ":"gCikis"};
      const key=km[col]||col.toLowerCase();
      const c=String(a[key]??"").localeCompare(String(b[key]??""),"tr",{numeric:true});
      return dir===1?c:-c;
    });
  })();

  return (
    <div>
      <div style={{display:"flex",gap:8,marginBottom:14,alignItems:"center",flexWrap:"wrap"}}>
        <Btn primary={mod==="bugun"} onClick={()=>setMod("bugun")}>BUGÜN</Btn>
        <Btn primary={mod==="hafta"} onClick={()=>setMod("hafta")}>BU HAFTA</Btn>
        <input type="date" defaultValue={basTarih} onBlur={e=>{ if(e.target.value?.length===10){setBasTarih(e.target.value);setMod("aralik");} }} onChange={e=>{ if(e.target.value?.length===10){setBasTarih(e.target.value);setMod("aralik");} }} style={inputStyle} />
        <span style={{fontSize:12,color:"var(--text-secondary)"}}>—</span>
        <input type="date" defaultValue={bitTarih} onBlur={e=>{ if(e.target.value?.length===10){setBitTarih(e.target.value);setMod("aralik");} }} onChange={e=>{ if(e.target.value?.length===10){setBitTarih(e.target.value);setMod("aralik");} }} style={inputStyle} />
        <label style={{display:"flex",alignItems:"center",gap:6,fontSize:12,cursor:"pointer",color:"var(--text-secondary)"}}>
          <input type="checkbox" checked={aciklamaGizle} onChange={e=>handleAciklamaGizle(e.target.checked)} />
          Açıklama Girilenleri Gizle
        </label>
        {mod==="hafta" && <span style={{fontSize:11,color:"var(--text-tertiary)"}}>{haftaPazartesi(BUGUN_TARIH)} — {BUGUN_TARIH}</span>}
        <span style={{display:"inline-flex",alignItems:"center",padding:"3px 12px",borderRadius:20,fontSize:12,fontWeight:600,background:hatalilar.length>0?"#FCEBEB":"#EAF3DE",color:hatalilar.length>0?"#A32D2D":"#3B6D11"}}>
          {hatalilar.length} hatalı hareket listelendi
        </span>
        <Btn style={{padding:"4px 10px",fontSize:11}} onClick={()=>{
          const visCols = cols.filter(c=>!hiddenCols.has(c));
          const rows = sortedHatalilar.flatMap(h=>h.hatalar.map(hata=>({
            "DEPARTMAN":h.departman,"GÖREV":h.gorev,"PERSONEL":`${h.ad} ${h.soyad}`,
            "TARİH":h.tarih,"SHIFT":h.shiftKod,"G.GİRİŞ":h.gGiris||"","G.ÇIKIŞ":h.gCikis||"",
            "HATA TÜRÜ":hata.tip,"AÇIKLAMA":hata.aciklama
          })));
          exportToExcel(rows, visCols, `hatali_hareketler_${new Date().toLocaleDateString("tr-TR")}.xlsx`);
        }}><span style={{fontSize:16}}>📥</span><span>Excel</span></Btn>
      </div>

      <div className="pdks-card">
        {hatalilar.length===0 ? (
          <div style={{padding:40,textAlign:"center",color:"var(--text-tertiary)",fontSize:13}}>✓ Bu dönemde hatalı hareket bulunmuyor</div>
        ) : (
          <div style={{padding:"8px 14px"}}>
            <DraggableTable cols={cols} setCols={setCols} hiddenCols={hiddenCols} setHiddenCols={setHiddenCols} onSortChange={s=>setSortState(s)}>
              <tbody>
                {sortedHatalilar.map((h) =>
                  h.hatalar.map((hata, hi2) => (
                    <tr key={`${h.id}-${hi2}`}>
                      {visibleCols.map(col=>(
                        <td key={col}>{cellVal(h, hata, col)}</td>
                      ))}
                    </tr>
                  ))
                )}
              </tbody>
            </DraggableTable>
          </div>
        )}
      </div>
    </div>
  );
};

// ─── PERSONEL LİSTESİ BİLEŞENİ ───────────────────────────────────────────────
const PERSONEL_COLS = ["SİCİL NO","TC KİMLİK","ADI","SOYADI","DEPARTMAN","GÖREV","İŞE GİRİŞ","İŞTEN ÇIKIŞ","DOLAP","LOJMAN","TELEFON","MAAS","DOĞUM","KAN","CİHAZ","KART"];

// Sütun → alan izni key eşleşmesi (KVKK)
const SUTUN_ALAN_MAP = {
  "TC KİMLİK": "personel_tc",
  "MAAS":      "personel_maas",
  "DOĞUM":     "personel_dogum",
  "KAN":       "personel_kan",
  "TELEFON":   "personel_telefon",
};

// Her render'da en güncel alan izinlerini localStorage'dan oku
const getGuncelAlanIzinleri = () => {
  try {
    const v = localStorage.getItem("pdks_alan_izinleri");
    if(v) {
      const saved = JSON.parse(v);
      return {...VARSAYILAN_ALAN_IZINLERI, ...saved};
    }
  } catch {}
  return VARSAYILAN_ALAN_IZINLERI;
};

const PersonelListesi = ({personeller, filteredPersonel, searchText, setSearchText, deptFilter, setDeptFilter, durumFilter, setDurumFilter, onKartAc, onYeniEkle, onKapat, uid="guest", readOnly=false, aktifKullanici=null, alanIzinleri=null}) => {
  const [cols, setCols, hiddenCols, setHiddenCols] = usePersistentCols(uid, "personel", PERSONEL_COLS);
  const [sortState, setSortState] = useState({col:null, dir:0});
  // Force re-render when alanIzinleri changes
  const [, forceUpdate] = useState(0);
  useEffect(() => { forceUpdate(n=>n+1); }, [alanIzinleri]);

  // Her render'da güncel alan izinlerini oku — prop veya localStorage
  const guncelAlanIzinleri = (() => {
    // Props'tan gelen state öncelikli (en güncel)
    if(alanIzinleri) return alanIzinleri;
    return getGuncelAlanIzinleri();
  })();

  // Kullanıcı için KVKK kısıtlamaları
  const izinliCols = aktifKullanici?.yetki==="admin"
    ? cols
    : cols.filter(c => {
        const alanKey = SUTUN_ALAN_MAP[c];
        if(!alanKey) return true; // KVKK alanı değil, her zaman göster
        const izin = guncelAlanIzinleri[alanKey];
        if(!izin) return false; // Tanımsız alan → gizle
        return izin.goster === true; // SADECE açıkça true ise göster
      });

  // Sütun adı → personel nesnesindeki alan adı map
  const COL_KEY = {"SİCİL NO":"sicil","TC KİMLİK":"tc","ADI":"ad","SOYADI":"soyad","DEPARTMAN":"departman","GÖREV":"gorev","İŞE GİRİŞ":"isGiris","İŞTEN ÇIKIŞ":"istenCikis","DOLAP":"dolapNo","LOJMAN":"lojmanNo","TELEFON":"telefon","MAAS":"maas","DOĞUM":"dogumTarihi","KAN":"kanGrubu","CİHAZ":"cihazNo"};

  const sortedRows = (() => {
    const {col, dir} = sortState;
    if(!col || dir===0) return filteredPersonel;
    const key = COL_KEY[col]||col.toLowerCase();
    const tarihSutunlari = new Set(["isGiris","istenCikis","dogumTarihi"]);
    const toNum = (t) => {
      if(!t) return 0;
      const p = t.includes("-") ? t.split("-") : t.split(".").reverse();
      return parseInt(p.join("")) || 0;
    };
    return [...filteredPersonel].sort((a,b)=>{
      if(tarihSutunlari.has(key)) {
        const c = toNum(a[key]) - toNum(b[key]);
        return dir===1?c:-c;
      }
      const va = String(a[key]??"").toLowerCase();
      const vb = String(b[key]??"").toLowerCase();
      const c = va.localeCompare(vb,"tr",{numeric:true});
      return dir===1?c:-c;
    });
  })();

  const cellVal = (p, col, onKartAc) => {
    switch(col) {
      case "SİCİL NO":    return <span style={{color:"#185FA5",fontWeight:600,cursor:"pointer"}} title={p.sicil}>{p.sicil}</span>;
      case "TC KİMLİK":   return <span style={{color:"var(--text-secondary)"}} title={p.tc}>{p.tc.substring(0,9)}...</span>;
      case "ADI":         return <span style={{fontWeight:600}}>{p.ad}</span>;
      case "SOYADI":      return <span style={{fontWeight:500}}>{p.soyad}</span>;
      case "DEPARTMAN":   return <span style={{color:"var(--text-secondary)"}} title={p.departman}>{p.departman}</span>;
      case "GÖREV":       return <span style={{color:"var(--text-secondary)"}} title={p.gorev}>{p.gorev}</span>;
      case "İŞE GİRİŞ":  return p.isGiris||"—";
      case "İŞTEN ÇIKIŞ": return <span style={{color:p.istenCikis?"#A32D2D":"var(--text-tertiary)"}}>{p.istenCikis||"—"}</span>;
      case "DOLAP":       return <span style={{color:"var(--text-tertiary)"}}>{p.dolapNo||"—"}</span>;
      case "LOJMAN":      return <span style={{color:"var(--text-tertiary)"}}>{p.lojmanNo||"—"}</span>;
      case "TELEFON":     return p.telefon||"—";
      case "MAAS":        return <span style={{fontWeight:500,textAlign:"right",display:"block"}}>{p.maas?Number(p.maas).toLocaleString("tr-TR"):0}</span>;
      case "DOĞUM":       return <span style={{color:"var(--text-secondary)"}}>{p.dogumTarihi||"—"}</span>;
      case "KAN":         return p.kanGrubu||"—";
      case "CİHAZ":       return <span style={{color:"var(--text-tertiary)"}}>{p.cihazNo||"0"}</span>;
      case "KART":        return <Btn style={{padding:"2px 6px",fontSize:10}} onClick={e=>{e.stopPropagation();onKartAc(p);}}>Kart</Btn>;
      default: return "—";
    }
  };

  return (
    <div style={{display:"flex",flexDirection:"column",height:"100%"}}>
      <div style={{display:"flex",gap:8,marginBottom:12,flexWrap:"wrap",alignItems:"center"}}>
        <div style={{position:"relative"}}>
          <span style={{position:"absolute",left:10,top:"50%",transform:"translateY(-50%)",color:"var(--text-tertiary)",fontSize:14,pointerEvents:"none"}}>🔍</span>
          <input value={searchText} onChange={e=>setSearchText(e.target.value)} placeholder="İsim, sicil, departman, görev..." style={{paddingLeft:32,padding:"7px 12px 7px 32px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)",width:260}} />
        </div>
        <Select value={deptFilter} onChange={e=>setDeptFilter(e.target.value)} style={{width:180}}>
          {aktifKullanici?.yetki==="admin"
            ? <><option value="TÜMÜ">Tüm Departmanlar</option>{
              // Tanımlı departmanlar + personel verisindeki bilinmeyen departmanlar
              [...new Set([...getDepartmanlar().map(d=>d.ad), ...personeller.map(p=>p.departman).filter(Boolean)])].sort()
              .map(ad=><option key={ad} value={ad}>{ad}</option>)
            }</>
            : <>{(aktifKullanici?.departmanlar||[]).length>1 && <option value="TÜMÜ">Tüm Departmanlar</option>}{(aktifKullanici?.departmanlar||[]).map(d=><option key={d}>{d}</option>)}</>
          }
        </Select>
        <Select value={durumFilter} onChange={e=>setDurumFilter(e.target.value)} style={{width:160}}>
          <option value="TÜMÜ">Hepsi</option>
          <option value="Çalışıyor">Çalışan Personeller</option>
          <option value="Ayrıldı">Ayrılanlar</option>
        </Select>
        <span style={{fontSize:12,color:"var(--text-tertiary)",marginLeft:"auto"}}>Kayıt sayısı: {filteredPersonel.length}</span>
      </div>

      <div className="pdks-card" style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden"}}>
        {aktifKullanici?.yetki!=="admin" && (
          <div style={{padding:"6px 14px",background:"#FAEEDA",borderBottom:"1px solid #854F0B",fontSize:11,color:"#854F0B",display:"flex",alignItems:"center",gap:6}}>
            🔒 KVKK kapsamındaki bazı alanlar yetkinize göre gizlenmiştir.
          </div>
        )}
        <div style={{flex:1,overflow:"auto",padding:"8px 12px"}}>
          <DraggableTable cols={izinliCols} setCols={v=>setCols(v)} hiddenCols={hiddenCols} setHiddenCols={setHiddenCols} onSortChange={s=>setSortState(s)}>
            <tbody>
              {sortedRows.map((p)=>(
                <tr key={p.id} style={{cursor:"pointer"}} onClick={()=>onKartAc(p)}>
                  {izinliCols.filter(c=>!hiddenCols.has(c)).map(col=>(
                    <td key={col} style={{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:120}}>
                      {cellVal(p, col, onKartAc)}
                    </td>
                  ))}
                </tr>
              ))}
              {sortedRows.length===0 && (
                <tr><td colSpan={izinliCols.length} style={{padding:24,textAlign:"center",color:"var(--text-tertiary)"}}>Kayıt bulunamadı</td></tr>
              )}
            </tbody>
          </DraggableTable>
        </div>
        <div style={{padding:"8px 12px",borderTop:"1px solid var(--grid-line)",display:"flex",gap:8,alignItems:"center",background:"var(--input-bg)",flexShrink:0}}>
          <Btn onClick={()=>{}}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
            Personel Raporları
          </Btn>
          <button onClick={()=>{
            const visCols = cols.filter(c=>!hiddenCols.has(c)).filter(c=>c!=="KART");
            const COL_KEY_E = {"SİCİL NO":"sicil","TC KİMLİK":"tc","ADI":"ad","SOYADI":"soyad","DEPARTMAN":"departman","GÖREV":"gorev","İŞE GİRİŞ":"isGiris","İŞTEN ÇIKIŞ":"istenCikis","DOLAP":"dolapNo","LOJMAN":"lojmanNo","TELEFON":"telefon","MAAS":"maas","DOĞUM":"dogumTarihi","KAN":"kanGrubu","CİHAZ":"cihazNo"};
            const rows = sortedRows.map(p=>{
              const row={};
              visCols.forEach(c=>{ row[c]=p[COL_KEY_E[c]]??""});
              return row;
            });
            exportToExcel(rows, visCols, `personel_listesi_${new Date().toLocaleDateString("tr-TR")}.xlsx`);
          }} style={{display:"flex",flexDirection:"column",alignItems:"center",gap:3,padding:"6px 10px",background:"var(--input-bg)",border:"1px solid var(--input-border)",borderRadius:6,cursor:"pointer",color:"var(--text-primary)",fontFamily:"var(--font-sans)",minWidth:58}}
            onMouseEnter={e=>e.currentTarget.style.background="var(--tr-hover)"}
            onMouseLeave={e=>e.currentTarget.style.background="var(--input-bg)"}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="12" y1="9" x2="12" y2="9"/></svg>
            <span style={{fontSize:10,whiteSpace:"nowrap",fontWeight:500}}>Excel'e Aktar</span>
          </button>
          <span style={{fontSize:11,color:"var(--text-tertiary)"}}>
            Toplam: {personeller.length} | Çalışan: {personeller.filter(p=>p.durum==="Çalışıyor").length} | Ayrılan: {personeller.filter(p=>p.durum==="Ayrıldı").length}
          </span>
          <div style={{marginLeft:"auto",display:"flex",gap:8}}>
            <Btn>🔄 Güncelle</Btn>
            {!readOnly && <Btn primary onClick={onYeniEkle}>+ Yeni Ekle</Btn>}
            <Btn danger onClick={onKapat}>✕ Kapat</Btn>
          </div>
        </div>
      </div>
    </div>
  );
};

// ─── TANIMLAR ────────────────────────────────────────────────────────────────
const Tanimlar = ({subMenu, aktifKullanici, alanIzinleri, setAlanIzni, personeller=[], onPersonelGuncelle}) => {
  // ─── TÜM STATE'LER BURADA — hooks koşullu çağrılamaz ───
  const canEdit = aktifKullanici?.yetki==="admin";

  // Kullanıcılar
  const [kullanicilar, setKullanicilar] = useState(getKullanicilar);
  const [editKul, setEditKul] = useState(null);
  const [showModal, setShowModal] = useState(false);
  const [yeniKul, setYeniKul] = useState({id:"",ad:"",soyad:"",sifre:"",yetki:"kullanici",departmanlar:[],aktif:true});

  // Shiftler
  const [shifts, setShiftsState] = useState(() => getShifts());
  const [editShift, setEditShift] = useState(null);
  const [showShiftModal, setShowShiftModal] = useState(false);
  const emptyShift = {kod:"",ad:"",giris:"",cikis:"",muafiyet:30,cikisMuafiyet:30,servisGiris:45,servisCikis:30,antraktGiris:"",antraktCikis:"",tanımliMesai:0,siraNo:1,yarimGun:false,kullanimda:true,araDinlenmeler:[],renk:"#3B6D11",bg:"#EAF3DE"};
  const [shiftForm, setShiftForm] = useState(emptyShift);

  // İzinler
  const [izinler, setIzinlerState] = useState(() => getIzinler());
  const [editIzin, setEditIzin] = useState(null);
  const [showIzinModal, setShowIzinModal] = useState(false);
  const emptyIzin = {kod:"",ad:"",renk:"#185FA5",bg:"#E6F1FB",tip:"ucretli"};
  const [izinForm, setIzinForm] = useState(emptyIzin);

  // Departmanlar
  const [deptList, setDeptList] = useState([...DEPARTMANLAR]);
  const [newDeptVal, setNewDeptVal] = useState("");
  const [editDeptIdx, setEditDeptIdx] = useState(null);
  const [editDeptVal, setEditDeptVal] = useState("");

  // Departmanlar (nesne formatı)
  const [deptObjList, setDeptObjList] = useState(() => getDepartmanlar());
  const [newAd, setNewAd]             = useState("");
  const [newAciklama, setNewAciklama] = useState("");
  const [deptEditIdx, setDeptEditIdx] = useState(null);
  const [deptEditAd, setDeptEditAd]   = useState("");
  const [deptEditAciklama, setDeptEditAciklama] = useState("");

  // Görevler
  const [gorevler, setGorevlerState] = useState(()=>getGorevler());
  const [seciliDept, setSeciliDept]  = useState(()=>getDepartmanlar()[0]?.ad||"");
  const [yeniGorevAd, setYeniGorevAd]             = useState("");
  const [yeniGorevAciklama, setYeniGorevAciklama] = useState("");
  const [gorevEditIdx, setGorevEditIdx]   = useState(null);
  const [gorevEditAd, setGorevEditAd]     = useState("");
  const [gorevEditAciklama, setGorevEditAciklama] = useState("");
  const [gorevEditSira, setGorevEditSira] = useState(1);
  const [yeniGorevKademe, setYeniGorevKademe]     = useState("Eleman");
  const [gorevEditKademe, setGorevEditKademe] = useState("Eleman");

  // Eski state (geriye uyumluluk)
  const [depts, setDepts] = useState([...DEPARTMANLAR]);
  const [newDept, setNewDept] = useState("");

  // Firma Parametreleri
  const FIRMA_LS_KEY = "pdks_firma_parametreleri";
  const FIRMA_VARSAYILAN = {
    // Firma Bilgileri
    firmaNo: "", sirketUnvani: "", cihazIpAdresi: "", cihazIpAciklama: "",
    // Puantaj Ayarları
    puantajCalismaYazisi: "1", maxDegisiklikGunu: 1,
    puantajUcretliIzinYazisi: "Üİ", puantajUcretsizIzinYazisi: "ÜS",
    yolUcretiHesapla: false, tatilHesapla: true,
    puantajTatilRengi: "#185FA5",
    departmanPuantajYetkisi: true, puantajToplami30GunAlsin: false,
    onbirsaatOncesiShiftAtamaOnayi: "onay", // yok|onay|engelle
    atanenIzinlerOnaydan: false, sabitTatilGunleri: {cumartesi:false, pazar:false},
    departmanIzinGirisYetkisi: true,
    // Bordro Entegrasyon
    bordroProgrami: "Logo", calismaAlani: "", bordroFirmaNo: "", connectionString: "",
  };
  const [firmaParams, setFirmaParamsState] = useState(() => {
    try { const v=localStorage.getItem(FIRMA_LS_KEY); return v?{...FIRMA_VARSAYILAN,...JSON.parse(v)}:FIRMA_VARSAYILAN; } catch { return FIRMA_VARSAYILAN; }
  });
  const saveFirmaParams = (p) => {
    setFirmaParamsState(p);
    try { localStorage.setItem(FIRMA_LS_KEY, JSON.stringify(p)); } catch {}
  };
  const fp = (key) => (val) => saveFirmaParams({...firmaParams, [key]: typeof val==="object"&&val?.target ? (val.target.type==="checkbox"?val.target.checked:val.target.value) : val});

  const [showAlanIzin, setShowAlanIzin] = useState(false);
  const [rtAcikYillar, setRtAcikYillar] = useState(() => new Set([String(new Date().getFullYear())]));

  // Resmi Tatiller
  const RT_LS_KEY = "pdks_resmi_tatiller";
  const VARSAYILAN_RT = [
    {tarih:"01.01.2026", ad:"Yılbaşı",                                    aciklama:"", katsayi:2},
    {tarih:"23.04.2026", ad:"Ulusal Egemenlik ve Çocuk Bayramı",          aciklama:"", katsayi:2},
    {tarih:"01.05.2026", ad:"Emek ve Dayanışma Günü",                     aciklama:"", katsayi:2},
    {tarih:"19.05.2026", ad:"Atatürk'ü Anma, Gençlik ve Spor Bayramı",   aciklama:"", katsayi:2},
    {tarih:"30.08.2026", ad:"Zafer Bayramı",                              aciklama:"", katsayi:2},
    {tarih:"29.10.2026", ad:"Cumhuriyet Bayramı",                         aciklama:"", katsayi:2},
  ];
  const [tatiller, setTatillerState] = useState(() => {
    try { const v=localStorage.getItem(RT_LS_KEY); return v?JSON.parse(v):VARSAYILAN_RT; } catch { return VARSAYILAN_RT; }
  });
  const [rtModal, setRtModal]   = useState(false);
  const [rtEdit, setRtEdit]     = useState(null); // null=yeni, obje=düzenle
  const [rtForm, setRtForm]     = useState({tarih:"", ad:"", aciklama:"", katsayi:2});

  const saveTatiller = (liste) => {
    setTatillerState(liste);
    try { localStorage.setItem(RT_LS_KEY, JSON.stringify(liste)); } catch {}
  };

  const kaydetKullanicilar = (liste) => { setKullanicilar(liste); saveKullanicilar(liste); };

  const silKullanici = (id) => {
    if(id === aktifKullanici?.id) { alert("Aktif kullanıcıyı silemezsiniz!"); return; }
    if(!confirm("Bu kullanıcıyı silmek istediğinizden emin misiniz?")) return;
    kaydetKullanicilar(kullanicilar.filter(k=>k.id!==id));
  };

  const kaydetForm = () => {
    const form = editKul || yeniKul;
    if(!form.id || !form.ad || !form.sifre) { alert("ID, Ad ve Şifre zorunludur."); return; }
    if(!editKul && kullanicilar.find(k=>k.id===form.id)) { alert("Bu kullanıcı ID zaten var!"); return; }
    if(editKul) {
      kaydetKullanicilar(kullanicilar.map(k=>k.id===form.id?form:k));
    } else {
      kaydetKullanicilar([...kullanicilar, form]);
    }
    setShowModal(false); setEditKul(null);
    setYeniKul({id:"",ad:"",soyad:"",sifre:"",yetki:"kullanici",departmanlar:[],aktif:true});
  };

  const KulModal = ({form, setForm}) => (
    <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:300}}>
      <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:500,maxHeight:"85vh",overflow:"auto"}}>
        <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
          <span style={{fontWeight:600,fontSize:15,color:"var(--text-primary)"}}>{editKul?"Kullanıcı Düzenle":"Yeni Kullanıcı"}</span>
          <button onClick={()=>{setShowModal(false);setEditKul(null);}} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-secondary)",fontSize:18}}>✕</button>
        </div>
        <div style={{padding:20}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12,marginBottom:12}}>
            <FormRow label="Kullanıcı ID (giriş adı)">
              <Input value={form.id} onChange={e=>setForm(p=>({...p,id:e.target.value.toLowerCase().replace(/\s/g,"")}))} placeholder="ornek_id" style={{opacity:editKul?.id?0.6:1}} />
            </FormRow>
            <FormRow label="Şifre">
              <Input value={form.sifre} onChange={e=>setForm(p=>({...p,sifre:e.target.value}))} placeholder="••••••••" type="text" />
            </FormRow>
            <FormRow label="Ad">
              <Input value={form.ad} onChange={e=>setForm(p=>({...p,ad:e.target.value}))} placeholder="Ad" />
            </FormRow>
            <FormRow label="Soyad">
              <Input value={form.soyad} onChange={e=>setForm(p=>({...p,soyad:e.target.value}))} placeholder="Soyad" />
            </FormRow>
          </div>

          <FormRow label="Yetki Seviyesi">
            <div style={{display:"flex",gap:8}}>
              {Object.entries(yetkiLabel).map(([val,lbl])=>(
                <label key={val} style={{flex:1,display:"flex",alignItems:"center",gap:8,padding:"10px 12px",border:`2px solid ${form.yetki===val?"#1565A0":"var(--grid-line)"}`,borderRadius:8,cursor:"pointer",background:form.yetki===val?"rgba(21,101,160,0.08)":"transparent"}}>
                  <input type="radio" name="yetki_modal" checked={form.yetki===val} onChange={()=>setForm(p=>({...p,yetki:val,departmanlar:val==="admin"?[]:p.departmanlar}))} style={{margin:0}} />
                  <div>
                    <div style={{fontSize:13,fontWeight:600,color:"var(--text-primary)"}}>{lbl}</div>
                    <div style={{fontSize:10,color:"var(--text-tertiary)"}}>{val==="admin"?"Tam yetki":val==="kullanici"?"Dept. bazlı":"Sadece görüntüle"}</div>
                  </div>
                </label>
              ))}
            </div>
          </FormRow>

          {form.yetki==="kullanici" && (
            <FormRow label="Erişim Departmanları">
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6,maxHeight:200,overflowY:"auto",padding:4}}>
                {DEPARTMANLAR.map(d=>(
                  <label key={d} style={{display:"flex",alignItems:"center",gap:8,padding:"6px 8px",border:`1px solid ${(form.departmanlar||[]).includes(d)?"#1565A0":"var(--grid-line)"}`,borderRadius:6,cursor:"pointer",background:(form.departmanlar||[]).includes(d)?"rgba(21,101,160,0.06)":"transparent",fontSize:12}}>
                    <input type="checkbox" checked={(form.departmanlar||[]).includes(d)} onChange={e=>{
                      setForm(p=>({...p,departmanlar:e.target.checked?[...(p.departmanlar||[]),d]:(p.departmanlar||[]).filter(x=>x!==d)}));
                    }} />
                    {d}
                  </label>
                ))}
              </div>
            </FormRow>
          )}

          {form.yetki!=="kullanici" && (
            <div style={{padding:"10px 12px",background:"var(--input-bg)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
              {form.yetki==="admin" ? "✓ Tüm departmanlara tam erişim" : "👁 Tüm departmanları görüntüleme yetkisi (düzenleme yok)"}
            </div>
          )}

          <FormRow label="">
            <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13}}>
              <input type="checkbox" checked={form.aktif!==false} onChange={e=>setForm(p=>({...p,aktif:e.target.checked}))} />
              <span style={{color:"var(--text-primary)"}}>Kullanıcı aktif</span>
            </label>
          </FormRow>
        </div>
        <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn onClick={()=>{setShowModal(false);setEditKul(null);}}>İptal</Btn>
          <Btn primary onClick={kaydetForm}>Kaydet</Btn>
        </div>
      </div>
    </div>
  );

  if(subMenu==="Kullanıcılar") {
    const canEdit = aktifKullanici?.yetki==="admin";
    return (
      <div>
        {showModal && <KulModal form={editKul||yeniKul} setForm={editKul ? setEditKul : setYeniKul} />}

        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
          <div>
            <div style={{fontSize:14,fontWeight:500,color:"var(--text-primary)"}}>Sistem Kullanıcıları</div>
            <div style={{fontSize:12,color:"var(--text-secondary)",marginTop:2}}>Toplam {kullanicilar.length} kullanıcı · {kullanicilar.filter(k=>k.aktif!==false).length} aktif</div>
          </div>
          {canEdit && <Btn primary onClick={()=>{setYeniKul({id:"",ad:"",soyad:"",sifre:"",yetki:"kullanici",departmanlar:[],aktif:true});setEditKul(null);setShowModal(true);}}>+ Yeni Kullanıcı</Btn>}
        </div>

        {!canEdit && (
          <div style={{padding:"10px 14px",background:"#FAEEDA",border:"1px solid #854F0B",borderRadius:8,fontSize:12,color:"#854F0B",marginBottom:14}}>
            🔒 Sadece görüntüleme — değişiklik için Admin yetkisi gerekli.
          </div>
        )}

        <div className="pdks-card">
          <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
            <thead>
              <tr>
                <th>KULLANICI ID</th><th>AD SOYAD</th><th>YETKİ</th><th>DEPARTMANLAR</th><th>DURUM</th>
                {canEdit && <th>İŞLEM</th>}
              </tr>
            </thead>
            <tbody>
              {kullanicilar.map((k,i)=>(
                <tr key={k.id}>
                  <td style={{fontWeight:600,color:"#185FA5",fontFamily:"monospace"}}>{k.id}</td>
                  <td style={{fontWeight:500}}>{k.ad} {k.soyad}</td>
                  <td>
                    <span style={{...yetkiRenk[k.yetki],padding:"3px 10px",borderRadius:20,fontSize:11,fontWeight:600}}>
                      {yetkiLabel[k.yetki]||k.yetki}
                    </span>
                  </td>
                  <td style={{color:"var(--text-secondary)",fontSize:12}}>
                    {k.yetki==="admin"
                      ? <span style={{color:"var(--text-tertiary)",fontStyle:"italic"}}>{k.yetki==="admin"?"Tüm departmanlar":"Tümü (görüntüle)"}</span>
                      : (k.departmanlar||[]).length===0
                        ? <span style={{color:"#A32D2D",fontSize:11}}>Departman atanmamış</span>
                        : <div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{(k.departmanlar||[]).map(d=><span key={d} style={{background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:4,padding:"1px 6px",fontSize:10}}>{d}</span>)}</div>
                    }
                  </td>
                  <td>
                    <span style={{padding:"3px 10px",borderRadius:20,fontSize:11,fontWeight:600,background:k.aktif!==false?"#EAF3DE":"#F1EFE8",color:k.aktif!==false?"#3B6D11":"#5F5E5A"}}>
                      {k.aktif!==false?"Aktif":"Pasif"}
                    </span>
                  </td>
                  {canEdit && (
                    <td>
                      <div style={{display:"flex",gap:6}}>
                        <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>{setEditKul({...k});setShowModal(true);}}>✏️ Düzenle</Btn>
                        {k.id!==aktifKullanici?.id && <Btn danger style={{padding:"3px 8px",fontSize:11}} onClick={()=>silKullanici(k.id)}>🗑️</Btn>}
                      </div>
                    </td>
                  )}
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Alan İzinleri — sadece admin görebilir ve ayarlayabilir */}
        {canEdit && (() => {
          const acikAlanlar = Object.values(alanIzinleri).filter(a=>a.goster).length;
          const toplamAlanlar = Object.keys(alanIzinleri).length;
          return (
            <div style={{marginTop:20,border:"1px solid var(--grid-line)",borderRadius:8,overflow:"hidden"}}>
              {/* Başlık — tıklanabilir */}
              <div onClick={()=>setShowAlanIzin(v=>!v)}
                style={{display:"flex",alignItems:"center",gap:8,padding:"10px 14px",background:"var(--input-bg)",cursor:"pointer",userSelect:"none"}}>
                <span style={{fontSize:13,fontWeight:600,color:"var(--text-primary)"}}>🔒 Alan İzinleri (KVKK)</span>
                <span style={{fontSize:11,color:"var(--text-secondary)",flex:1}}>
                  — {acikAlanlar}/{toplamAlanlar} alan açık
                </span>
                <span style={{fontSize:11,color:"var(--text-tertiary)"}}>{showAlanIzin?"▲":"▼"}</span>
              </div>
              {/* İçerik */}
              {showAlanIzin && (
                <div style={{padding:14,background:"var(--card-bg)"}}>
                  <div style={{fontSize:12,color:"var(--text-secondary)",marginBottom:12}}>
                    "Göster" seçilirse tüm kullanıcılar görebilir. "Gizle" seçilirse sadece Admin görür.
                  </div>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                    {Object.entries(alanIzinleri).map(([key, alan])=>(
                      <div key={key} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",background:"var(--input-bg)",border:`1.5px solid ${alan.goster?"var(--grid-line)":"#A32D2D33"}`,borderRadius:8}}>
                        <div>
                          <div style={{fontSize:12,fontWeight:500,color:"var(--text-primary)"}}>{alan.label}</div>
                          {alan.kvkk && <div style={{fontSize:10,color:"#854F0B",marginTop:1}}>🔒 KVKK</div>}
                        </div>
                        <div style={{display:"flex",gap:4}}>
                          {[true,false].map(val=>(
                            <button key={String(val)} onClick={()=>setAlanIzni(key, val)}
                              style={{
                                padding:"4px 10px",borderRadius:6,fontSize:11,cursor:"pointer",fontWeight:600,
                                border:`1.5px solid ${alan.goster===val?(val?"#1565A0":"#A32D2D"):"var(--grid-line)"}`,
                                background:alan.goster===val?(val?"#1565A0":"#A32D2D"):"transparent",
                                color:alan.goster===val?"#fff":"var(--text-secondary)",
                              }}>
                              {val?"Göster":"Gizle"}
                            </button>
                          ))}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </div>
          );
        })()}

        <div style={{marginTop:16,padding:14,background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
          <div style={{fontWeight:600,marginBottom:8,color:"var(--text-primary)"}}>Yetki Seviyeleri</div>
          <div style={{display:"flex",gap:16,flexWrap:"wrap"}}>
            <div style={{display:"flex",alignItems:"center",gap:8}}>
              <span style={{...yetkiRenk.admin,padding:"2px 8px",borderRadius:20,fontSize:11,fontWeight:600}}>Admin</span>
              <span>→ Tüm departmanlar, tüm ekranlar, tüm alanlar, tam yetki</span>
            </div>
            <div style={{display:"flex",alignItems:"center",gap:8}}>
              <span style={{...yetkiRenk.kullanici,padding:"2px 8px",borderRadius:20,fontSize:11,fontWeight:600}}>Kullanıcı</span>
              <span>→ Sadece atanan departmanlar · Giriş/Çıkış ekranı yok · Sadece Shift Atama'da değişiklik · KVKK alanları gizli</span>
            </div>
          </div>
        </div>
      </div>
    );
  }

  if(subMenu==="İzinler") {
    const kaydetIzin = () => {
      if(!izinForm.kod||!izinForm.ad) { alert("Kod ve Ad zorunludur."); return; }
      let yeni;
      if(editIzin) {
        yeni = izinler.map(s=>s.kod===editIzin.kod?izinForm:s);
      } else {
        if(izinler.find(s=>s.kod===izinForm.kod)) { alert("Bu kod zaten var!"); return; }
        yeni = [...izinler, izinForm];
      }
      saveIzinler(yeni); IZINLER.length=0; yeni.forEach(s=>IZINLER.push(s));
      setIzinlerState(yeni); setShowIzinModal(false); setEditIzin(null); setIzinForm(emptyIzin);
    };
    const silIzin = (kod) => {
      // Shift atama verilerinde kullanılıyor mu?
      const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();
      const shiftKullanan = Object.entries(shiftData).filter(([,v])=>v===kod);
      if(shiftKullanan.length > 0) {
        alert(`"${kod}" izni ${shiftKullanan.length} kişinin shift atamasında kullanılıyor.\nSilmeden önce bu atamaları değiştirin.`);
        return;
      }
      // Personel hareketlerinde kullanılıyor mu?
      const hareketler = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):[]; } catch{return[];} })();
      const hareketKullanan = hareketler.filter(h=>h.shiftKod===kod);
      if(hareketKullanan.length > 0) {
        alert(`"${kod}" izni ${hareketKullanan.length} personel hareketinde kullanılıyor.\nSilmeden önce bu kayıtları değiştirin.`);
        return;
      }
      if(!confirm(`"${kod}" izin kodunu silmek istiyor musunuz?`)) return;
      const yeni = izinler.filter(s=>s.kod!==kod);
      saveIzinler(yeni); IZINLER.length=0; yeni.forEach(s=>IZINLER.push(s)); setIzinlerState(yeni);
    };

    const ucretliler = izinler.filter(s=>s.tip!=="ucretsiz");
    const ucretsizler = izinler.filter(s=>s.tip==="ucretsiz");

    const IzinTablosu = ({liste, baslik, renk, bgRenk}) => (
      <div style={{marginBottom:20}}>
        <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:10}}>
          <div style={{width:3,height:16,background:renk,borderRadius:2}} />
          <span style={{fontSize:13,fontWeight:700,color:renk}}>{baslik}</span>
          <span style={{fontSize:11,color:"var(--text-tertiary)",background:"var(--input-bg)",padding:"1px 8px",borderRadius:20}}>{liste.length}</span>
        </div>
        <div style={{display:"flex",flexWrap:"wrap",gap:8,justifyContent:"flex-start",alignItems:"flex-start",width:"100%",marginLeft:0}}>
          {liste.map(s=>(
            <div key={s.kod} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 12px",background:"var(--card-bg)",border:`1px solid var(--grid-line)`,borderRadius:8,borderLeft:`3px solid ${s.renk}`,width:210,flexShrink:0}}>
              <span style={{background:s.bg,color:s.renk,padding:"3px 8px",borderRadius:5,fontSize:12,fontWeight:700,flexShrink:0,minWidth:32,textAlign:"center"}}>{s.kod}</span>
              <span style={{fontSize:13,fontWeight:500,flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{s.ad}</span>
              {canEdit && <div style={{display:"flex",gap:3,flexShrink:0}}>
                <button onClick={()=>{setIzinForm({tip:"ucretli",...s});setEditIzin(s);setShowIzinModal(true);}} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-tertiary)",fontSize:13,padding:"2px 4px",borderRadius:4}} onMouseEnter={e=>e.currentTarget.style.color="var(--text-primary)"} onMouseLeave={e=>e.currentTarget.style.color="var(--text-tertiary)"}>✏️</button>
                <button onClick={()=>silIzin(s.kod)} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-tertiary)",fontSize:13,padding:"2px 4px",borderRadius:4}} onMouseEnter={e=>e.currentTarget.style.color="#A32D2D"} onMouseLeave={e=>e.currentTarget.style.color="var(--text-tertiary)"}>🗑️</button>
              </div>}
            </div>
          ))}
          {liste.length===0 && <div style={{fontSize:12,color:"var(--text-tertiary)",padding:"10px 0"}}>Bu tipte izin yok</div>}
        </div>
      </div>
    );

    return (
      <div>
        {showIzinModal && (
          <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:300}}>
            <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:460}}>
              <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <span style={{fontWeight:600,fontSize:15}}>{editIzin?"İzin Düzenle":"Yeni İzin Kodu"}</span>
                <button onClick={()=>{setShowIzinModal(false);setEditIzin(null);setIzinForm(emptyIzin);}} style={{background:"none",border:"none",cursor:"pointer",fontSize:18,color:"var(--text-secondary)"}}>✕</button>
              </div>
              <div style={{padding:20,display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
                <FormRow label="Harf Kodu (MAX 3)">
                  <Input value={izinForm.kod} onChange={e=>setIzinForm(p=>({...p,kod:e.target.value.toUpperCase().slice(0,3)}))} placeholder="YI" readOnly={!!editIzin} style={{opacity:editIzin?0.6:1}} />
                </FormRow>
                <FormRow label="İzin Adı">
                  <Input value={izinForm.ad} onChange={e=>setIzinForm(p=>({...p,ad:e.target.value}))} placeholder="Yıllık İzin" />
                </FormRow>
                <FormRow label="İzin Tipi" style={{gridColumn:"1/-1"}}>
                  <div style={{display:"flex",gap:16}}>
                    <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13,padding:"8px 16px",borderRadius:8,border:`2px solid ${izinForm.tip==="ucretli"?"#185FA5":"var(--grid-line)"}`,background:izinForm.tip==="ucretli"?"#E6F1FB":"transparent",color:izinForm.tip==="ucretli"?"#185FA5":"var(--text-secondary)"}}>
                      <input type="radio" name="izinTip" checked={izinForm.tip!=="ucretsiz"} onChange={()=>setIzinForm(p=>({...p,tip:"ucretli"}))} />
                      ✅ Ücretli İzin
                    </label>
                    <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13,padding:"8px 16px",borderRadius:8,border:`2px solid ${izinForm.tip==="ucretsiz"?"#A32D2D":"var(--grid-line)"}`,background:izinForm.tip==="ucretsiz"?"#FCEBEB":"transparent",color:izinForm.tip==="ucretsiz"?"#A32D2D":"var(--text-secondary)"}}>
                      <input type="radio" name="izinTip" checked={izinForm.tip==="ucretsiz"} onChange={()=>setIzinForm(p=>({...p,tip:"ucretsiz"}))} />
                      ❌ Ücretsiz İzin
                    </label>
                  </div>
                </FormRow>
                <FormRow label="Metin Rengi">
                  <div style={{display:"flex",gap:8,alignItems:"center"}}>
                    <input type="color" value={izinForm.renk} onChange={e=>setIzinForm(p=>({...p,renk:e.target.value}))} style={{width:40,height:36,border:"none",cursor:"pointer",background:"none"}} />
                    <Input value={izinForm.renk} onChange={e=>setIzinForm(p=>({...p,renk:e.target.value}))} style={{flex:1}} />
                  </div>
                </FormRow>
                <FormRow label="Arkaplan Rengi">
                  <div style={{display:"flex",gap:8,alignItems:"center"}}>
                    <input type="color" value={izinForm.bg} onChange={e=>setIzinForm(p=>({...p,bg:e.target.value}))} style={{width:40,height:36,border:"none",cursor:"pointer",background:"none"}} />
                    <Input value={izinForm.bg} onChange={e=>setIzinForm(p=>({...p,bg:e.target.value}))} style={{flex:1}} />
                  </div>
                </FormRow>
                <div style={{gridColumn:"1/-1",display:"flex",alignItems:"center",gap:12,padding:"10px 14px",background:"var(--input-bg)",borderRadius:8}}>
                  <span style={{fontSize:12,color:"var(--text-secondary)"}}>Önizleme:</span>
                  <span style={{background:izinForm.bg,color:izinForm.renk,padding:"4px 14px",borderRadius:6,fontSize:13,fontWeight:700}}>{izinForm.kod||"KOD"} — {izinForm.ad||"İzin Adı"}</span>
                  <span style={{marginLeft:"auto",fontSize:11,padding:"2px 8px",borderRadius:20,background:izinForm.tip==="ucretsiz"?"#FCEBEB":"#E6F1FB",color:izinForm.tip==="ucretsiz"?"#A32D2D":"#185FA5",fontWeight:600}}>{izinForm.tip==="ucretsiz"?"Ücretsiz":"Ücretli"}</span>
                </div>
              </div>
              <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
                <Btn onClick={()=>{setShowIzinModal(false);setEditIzin(null);setIzinForm(emptyIzin);}}>İptal</Btn>
                <Btn primary onClick={kaydetIzin}>Kaydet</Btn>
              </div>
            </div>
          </div>
        )}

        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16}}>
          <div style={{fontSize:14,fontWeight:500}}>İzin Kodları — Shift Atama ekranında İZİN satırında görünür</div>
          {canEdit && <Btn primary onClick={()=>{setIzinForm(emptyIzin);setEditIzin(null);setShowIzinModal(true);}}>Yeni İzin Kodu</Btn>}
        </div>

        <IzinTablosu liste={ucretliler} baslik="✅ Ücretli İzinler" renk="#185FA5" />
        <IzinTablosu liste={ucretsizler} baslik="❌ Ücretsiz / Devamsız" renk="#A32D2D" />
      </div>
    );
  }

  if(subMenu==="Shiftler") {
    const kaydetShift = () => {
      if(!shiftForm.kod||!shiftForm.ad) { alert("Kod ve Ad zorunludur."); return; }
      let yeni;
      if(editShift) {
        yeni = shifts.map(s=>s.kod===editShift.kod?shiftForm:s);
      } else {
        if(shifts.find(s=>s.kod===shiftForm.kod)) { alert("Bu kod zaten var!"); return; }
        yeni = [...shifts, shiftForm];
      }
      saveShifts(yeni); const sirali=siralanmisShifts(yeni); SHIFTS.length=0; sirali.forEach(s=>SHIFTS.push(s));
      setShiftsState(sirali); setShowShiftModal(false); setEditShift(null); setShiftForm(emptyShift);
    };

    const silShift = (kod) => {
      // Shift atama verilerinde kullanılıyor mu?
      const shiftData = (() => { try { const v=localStorage.getItem("pdks_shift_data"); return v?JSON.parse(v):{}; } catch{return{};} })();
      const shiftKullanan = Object.entries(shiftData).filter(([,v])=>v===kod);
      if(shiftKullanan.length > 0) {
        alert(`"${kod}" vardiyası ${shiftKullanan.length} kişinin shift atamasında kullanılıyor.\nSilmeden önce bu atamaları değiştirin.`);
        return;
      }
      // Personel hareketlerinde kullanılıyor mu?
      const hareketler = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):[]; } catch{return[];} })();
      const hareketKullanan = hareketler.filter(h=>h.shiftKod===kod);
      if(hareketKullanan.length > 0) {
        alert(`"${kod}" vardiyası ${hareketKullanan.length} personel hareketinde kullanılıyor.\nSilmeden önce bu kayıtları değiştirin.`);
        return;
      }
      if(!confirm(`"${kod}" vardiyasını silmek istiyor musunuz?`)) return;
      const yeni = shifts.filter(s=>s.kod!==kod);
      saveShifts(yeni); const sirali=siralanmisShifts(yeni); SHIFTS.length=0; sirali.forEach(s=>SHIFTS.push(s)); setShiftsState(sirali); setShowShiftModal(false); setEditShift(null); setShiftForm(emptyShift);
    };

    const timeInput = (label, val, key) => (
      <div>
        <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>{label}</div>
        <input type="time" value={val||""} onChange={e=>setShiftForm(p=>({...p,[key]:e.target.value}))}
          style={{padding:"7px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:13,width:"100%"}} />
      </div>
    );

    return (
      <div>
        {showShiftModal && (
          <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:300}}>
            <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:560,maxHeight:"85vh",overflow:"auto"}}>
              <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <span style={{fontWeight:600,fontSize:15}}>{editShift?"Vardiya Düzenle":"Yeni Vardiya"}</span>
                <button onClick={()=>{setShowShiftModal(false);setEditShift(null);setShiftForm(emptyShift);}} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-secondary)",fontSize:18}}>✕</button>
              </div>
              <div style={{padding:20,overflowY:"auto",maxHeight:"70vh"}}>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:12}}>
                  <FormRow label="Harf Kodu (MAX 3)">
                    <Input value={shiftForm.kod} onChange={e=>setShiftForm(p=>({...p,kod:e.target.value.toUpperCase().slice(0,3)}))} placeholder="A" style={{opacity:editShift?0.6:1}} readOnly={!!editShift} />
                  </FormRow>
                  <FormRow label="Vardiya Adı">
                    <Input value={shiftForm.ad} onChange={e=>setShiftForm(p=>({...p,ad:e.target.value}))} placeholder="A Vardiyası" />
                  </FormRow>
                  {timeInput("Çalışma Başlangıç", shiftForm.giris, "giris")}
                  {timeInput("Çalışma Bitiş", shiftForm.cikis, "cikis")}
                  <FormRow label="Giriş Muafiyet (dk)">
                    <Input type="number" value={shiftForm.muafiyet} onChange={e=>setShiftForm(p=>({...p,muafiyet:+e.target.value}))} placeholder="30" />
                  </FormRow>
                  <FormRow label="Çıkış Muafiyet (dk)">
                    <Input type="number" value={shiftForm.cikisMuafiyet||0} onChange={e=>setShiftForm(p=>({...p,cikisMuafiyet:+e.target.value}))} placeholder="30" />
                  </FormRow>
                  <FormRow label="Giriş Servis (dk)">
                    <Input type="number" value={shiftForm.servisGiris||0} onChange={e=>setShiftForm(p=>({...p,servisGiris:+e.target.value}))} placeholder="45" />
                  </FormRow>
                  <FormRow label="Çıkış Servis (dk)">
                    <Input type="number" value={shiftForm.servisCikis||0} onChange={e=>setShiftForm(p=>({...p,servisCikis:+e.target.value}))} placeholder="30" />
                  </FormRow>
                  {timeInput("Antract Giriş", shiftForm.antraktGiris, "antraktGiris")}
                  {timeInput("Antract Çıkış", shiftForm.antraktCikis, "antraktCikis")}
                  <FormRow label="Tanımlı Mesai (dk)">
                    <div style={{display:"flex",gap:6}}>
                      <Input type="number" value={shiftForm.tanımliMesai||0} onChange={e=>setShiftForm(p=>({...p,tanımliMesai:+e.target.value}))} placeholder="0" />
                      <Btn style={{padding:"4px 10px",fontSize:12,flexShrink:0}} onClick={()=>{
                        if(shiftForm.giris&&shiftForm.cikis){
                          const g=shiftForm.giris.split(":").map(Number); const c=shiftForm.cikis.split(":").map(Number);
                          let dk=(c[0]*60+c[1])-(g[0]*60+g[1]); if(dk<0)dk+=1440;
                          const antraktDk=shiftForm.antraktGiris&&shiftForm.antraktCikis?((shiftForm.antraktCikis.split(":").map(Number)[0]*60+shiftForm.antraktCikis.split(":").map(Number)[1])-(shiftForm.antraktGiris.split(":").map(Number)[0]*60+shiftForm.antraktGiris.split(":").map(Number)[1])):0;
                          setShiftForm(p=>({...p,tanımliMesai:dk-antraktDk}));
                        }
                      }}>Hesapla</Btn>
                    </div>
                  </FormRow>
                  <FormRow label="Sıra No">
                    <Input type="number" value={shiftForm.siraNo||1} onChange={e=>setShiftForm(p=>({...p,siraNo:+e.target.value}))} placeholder="1" />
                  </FormRow>
                  <FormRow label="Metin Rengi">
                    <div style={{display:"flex",gap:8,alignItems:"center"}}>
                      <input type="color" value={shiftForm.renk} onChange={e=>setShiftForm(p=>({...p,renk:e.target.value}))} style={{width:40,height:36,border:"none",cursor:"pointer",background:"none"}} />
                      <Input value={shiftForm.renk} onChange={e=>setShiftForm(p=>({...p,renk:e.target.value}))} style={{flex:1}} />
                    </div>
                  </FormRow>
                  <FormRow label="Arkaplan Rengi">
                    <div style={{display:"flex",gap:8,alignItems:"center"}}>
                      <input type="color" value={shiftForm.bg} onChange={e=>setShiftForm(p=>({...p,bg:e.target.value}))} style={{width:40,height:36,border:"none",cursor:"pointer",background:"none"}} />
                      <Input value={shiftForm.bg} onChange={e=>setShiftForm(p=>({...p,bg:e.target.value}))} style={{flex:1}} />
                    </div>
                  </FormRow>
                  <div style={{gridColumn:"1/-1",display:"flex",gap:20,alignItems:"center",padding:"10px 14px",background:"var(--input-bg)",borderRadius:8}}>
                    <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13}}>
                      <input type="checkbox" checked={shiftForm.yarimGun||false} onChange={e=>setShiftForm(p=>({...p,yarimGun:e.target.checked}))} />
                      Yarım Gün
                    </label>
                    <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13}}>
                      <input type="checkbox" checked={shiftForm.kullanimda!==false} onChange={e=>setShiftForm(p=>({...p,kullanimda:e.target.checked}))} />
                      Kullanımda
                    </label>
                    <span style={{marginLeft:"auto",fontSize:12,color:"var(--text-secondary)"}}>Önizleme:</span>
                    <span style={{background:shiftForm.bg,color:shiftForm.renk,padding:"4px 14px",borderRadius:6,fontSize:13,fontWeight:700}}>
                      {shiftForm.kod||"KOD"}{shiftForm.giris&&shiftForm.cikis?` (${shiftForm.giris}-${shiftForm.cikis})`:""}
                    </span>
                  </div>
                </div>

                {/* Ara Dinlenme Saatleri */}
                <div style={{marginTop:4}}>
                  <div style={{fontSize:12,fontWeight:600,color:"var(--text-secondary)",marginBottom:8}}>ARA DİNLENME SAATLERİ</div>
                  <div style={{border:"1px solid var(--grid-line)",borderRadius:8,overflow:"hidden"}}>
                    <div style={{display:"flex",gap:8,padding:"8px 10px",borderBottom:"1px solid var(--grid-line)",background:"var(--input-bg)"}}>
                      <input placeholder="Açıklama" id="dinlenme_aciklama" style={{flex:2,padding:"5px 8px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--card-bg)",color:"var(--text-primary)",fontSize:12}} />
                      <input type="time" id="dinlenme_bas" style={{flex:1,padding:"5px 8px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--card-bg)",color:"var(--text-primary)",fontSize:12,colorScheme:"dark"}} />
                      <span style={{alignSelf:"center",color:"var(--text-tertiary)"}}>—</span>
                      <input type="time" id="dinlenme_bit" style={{flex:1,padding:"5px 8px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--card-bg)",color:"var(--text-primary)",fontSize:12,colorScheme:"dark"}} />
                      <Btn style={{padding:"4px 10px",fontSize:12,flexShrink:0}} onClick={()=>{
                        const ac=document.getElementById("dinlenme_aciklama").value;
                        const bs=document.getElementById("dinlenme_bas").value;
                        const bt=document.getElementById("dinlenme_bit").value;
                        if(!bs||!bt) return;
                        const dk=bs&&bt?((bt.split(":").map(Number)[0]*60+bt.split(":").map(Number)[1])-(bs.split(":").map(Number)[0]*60+bs.split(":").map(Number)[1])):0;
                        setShiftForm(p=>({...p,araDinlenmeler:[...(p.araDinlenmeler||[]),{aciklama:ac,baslangic:bs,bitis:bt,sure:dk}]}));
                        document.getElementById("dinlenme_aciklama").value="";
                        document.getElementById("dinlenme_bas").value="";
                        document.getElementById("dinlenme_bit").value="";
                      }}>Ekle</Btn>
                    </div>
                    <table style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
                      <thead><tr style={{background:"var(--th-bg)",color:"#fff"}}>
                        <th style={{padding:"6px 10px",textAlign:"left"}}>Açıklama</th>
                        <th style={{padding:"6px 10px",textAlign:"center"}}>Başlangıç</th>
                        <th style={{padding:"6px 10px",textAlign:"center"}}>Bitiş</th>
                        <th style={{padding:"6px 10px",textAlign:"center"}}>Süre</th>
                        <th style={{padding:"6px 10px",textAlign:"center"}}></th>
                      </tr></thead>
                      <tbody>
                        {(shiftForm.araDinlenmeler||[]).length===0
                          ? <tr><td colSpan={5} style={{padding:"12px",textAlign:"center",color:"var(--text-tertiary)"}}>Ara dinlenme eklenmedi</td></tr>
                          : (shiftForm.araDinlenmeler||[]).map((d,i)=>(
                            <tr key={i} style={{borderTop:"1px solid var(--grid-line)"}}>
                              <td style={{padding:"6px 10px"}}>{d.aciklama||"—"}</td>
                              <td style={{padding:"6px 10px",textAlign:"center",fontFamily:"monospace"}}>{d.baslangic}</td>
                              <td style={{padding:"6px 10px",textAlign:"center",fontFamily:"monospace"}}>{d.bitis}</td>
                              <td style={{padding:"6px 10px",textAlign:"center"}}>{d.sure} dk</td>
                              <td style={{padding:"6px 10px",textAlign:"center"}}>
                                <Btn danger style={{padding:"2px 8px",fontSize:11}} onClick={()=>setShiftForm(p=>({...p,araDinlenmeler:p.araDinlenmeler.filter((_,j)=>j!==i)}))}>Sil</Btn>
                              </td>
                            </tr>
                          ))
                        }
                      </tbody>
                    </table>
                  </div>
                </div>
              </div>
              <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
                <Btn onClick={()=>{setShowShiftModal(false);setEditShift(null);setShiftForm(emptyShift);}}>İptal</Btn>
                <Btn primary onClick={kaydetShift}>Kaydet</Btn>
              </div>
            </div>
          </div>
        )}
        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
          <div style={{fontSize:14,fontWeight:500,color:"var(--text-primary)"}}>Vardiyalar ({shifts.length})</div>
          {canEdit && <Btn primary onClick={()=>{setShiftForm(emptyShift);setEditShift(null);setShowShiftModal(true);}}>+ Yeni Vardiya</Btn>}
        </div>
        <div className="pdks-card">
          <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
            <thead><tr>
              <th>S.</th><th>KOD</th><th>AD</th><th>GİRİŞ</th><th>ÇIKIŞ</th><th>G.MUF</th><th>Ç.MUF</th><th>G.SERVİS</th><th>Ç.SERVİS</th><th>ANTRACT</th><th>T.MESAİ</th><th>DURUM</th>
              {canEdit && <th>İŞLEM</th>}
            </tr></thead>
            <tbody>{siralanmisShifts(shifts).map((s,i)=>(
              <tr key={s.kod}>
                <td style={{textAlign:"center",color:"var(--text-tertiary)",fontSize:11}}>{s.siraNo||i+1}</td>
                <td><span style={{background:s.bg,color:s.renk,padding:"3px 10px",borderRadius:5,fontSize:12,fontWeight:700}}>{s.kod}</span></td>
                <td style={{fontWeight:500}}>{s.ad}</td>
                <td style={{fontFamily:"monospace"}}>{s.giris||"—"}</td>
                <td style={{fontFamily:"monospace"}}>{s.cikis||"—"}</td>
                <td style={{textAlign:"center",fontSize:11}}>{s.muafiyet?`${s.muafiyet}dk`:"—"}</td>
                <td style={{textAlign:"center",fontSize:11}}>{s.cikisMuafiyet?`${s.cikisMuafiyet}dk`:"—"}</td>
                <td style={{textAlign:"center",fontSize:11}}>{s.servisGiris?`${s.servisGiris}dk`:"—"}</td>
                <td style={{textAlign:"center",fontSize:11}}>{s.servisCikis?`${s.servisCikis}dk`:"—"}</td>
                <td style={{fontSize:11,color:"var(--text-secondary)"}}>{s.antraktGiris&&s.antraktCikis?`${s.antraktGiris}-${s.antraktCikis}`:"—"}</td>
                <td style={{textAlign:"center",fontSize:11}}>{s.tanımliMesai?`${s.tanımliMesai}dk`:"—"}</td>
                <td>
                  <span style={{fontSize:10,padding:"2px 7px",borderRadius:20,fontWeight:600,background:s.kullanimda!==false?"#EAF3DE":"#F1EFE8",color:s.kullanimda!==false?"#3B6D11":"#5F5E5A"}}>
                    {s.kullanimda!==false?"Aktif":"Pasif"}
                  </span>
                  {s.yarimGun&&<span style={{marginLeft:4,fontSize:10,color:"#185FA5"}}>½</span>}
                </td>
                {canEdit && <td><div style={{display:"flex",gap:5}}>
                  <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>{setShiftForm({araDinlenmeler:[],...s});setEditShift(s);setShowShiftModal(true);}}>✏️</Btn>
                  <Btn danger style={{padding:"3px 8px",fontSize:11}} onClick={()=>silShift(s.kod)}>🗑️</Btn>
                </div></td>}
              </tr>
            ))}</tbody>
          </table>
        </div>
      </div>
    );
  }

  if(subMenu==="Departmanlar") {
    // State'ler Tanimlar başında tanımlı
    const kaydet = (liste) => { setDeptObjList(liste); saveDepartmanlar(liste); };

    const ekle = () => {
      const v = newAd.trim().toUpperCase();
      if(!v) return;
      if(deptObjList.find(d=>d.ad===v)) { alert("Bu departman zaten var!"); return; }
      kaydet([...deptObjList, {ad:v, aciklama:newAciklama.trim()}]);
      setNewAd(""); setNewAciklama("");
    };

    const duzenlemeKaydet = (i) => {
      const v = deptEditAd.trim().toUpperCase();
      if(!v) return;
      const eskiAd = deptObjList[i].ad;
      const yeni = deptObjList.map((d,idx)=>idx===i?{ad:v, aciklama:deptEditAciklama.trim()}:d);
      kaydet(yeni);
      // Departman adı değiştiyse personelleri de güncelle
      if(eskiAd !== v && onPersonelGuncelle) {
        onPersonelGuncelle(prev => {
          const guncellenmis = prev.map(p => p.departman===eskiAd ? {...p, departman:v} : p);
          try { localStorage.setItem("pdks_personeller", JSON.stringify(guncellenmis)); } catch {}
          return guncellenmis;
        });
      }
      setDeptEditIdx(null);
    };

    const sil = (dept) => {
      const kullanan = personeller.filter(p=>p.departman===dept.ad);
      if(kullanan.length>0) {
        alert(`"${dept.ad}" departmanına ait ${kullanan.length} personel var. Silmeden önce bu kişilerin departmanını değiştirin.`);
        return;
      }
      // Personel hareketlerinde kullanılıyor mu?
      const hareketler = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):[]; } catch{return[];} })();
      const hareketKullanan = hareketler.filter(h=>h.departman===dept.ad);
      if(hareketKullanan.length>0) {
        alert(`"${dept.ad}" departmanı ${hareketKullanan.length} personel hareketinde kayıtlı.\nSilmeden önce bu kayıtları temizleyin.`);
        return;
      }
      if(!confirm(`"${dept.ad}" departmanını silmek istiyor musunuz?`)) return;
      kaydet(deptObjList.filter((_,i)=>deptObjList.indexOf(_)!==-1 && _ !== dept));
    };

    return (
      <div>
        {canEdit && (
          <div style={{display:"flex",gap:8,marginBottom:14,alignItems:"flex-end",flexWrap:"wrap"}}>
            <div>
              <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>Departman Adı</div>
              <Input value={newAd} onChange={e=>setNewAd(e.target.value.toUpperCase())} placeholder="ör. ANİMASYON" style={{width:200}} onKeyDown={e=>e.key==="Enter"&&ekle()} />
            </div>
            <div style={{flex:1}}>
              <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>Açıklama (opsiyonel)</div>
              <Input value={newAciklama} onChange={e=>setNewAciklama(e.target.value)} placeholder="Departman hakkında kısa açıklama..." onKeyDown={e=>e.key==="Enter"&&ekle()} />
            </div>
            <Btn primary onClick={ekle}>Ekle</Btn>
          </div>
        )}
        <div className="pdks-card">
          <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
            <thead><tr>
              <th style={{width:36}}>#</th>
              <th>Departman Adı</th>
              <th>Açıklama</th>
              <th style={{width:40}}>Personel</th>
              {canEdit && <th style={{width:100}}>İşlem</th>}
            </tr></thead>
            <tbody>{deptObjList.map((dept,i)=>(
              <tr key={i}>
                <td style={{color:"var(--text-tertiary)",textAlign:"center"}}>{i+1}</td>
                <td>
                  {deptEditIdx===i
                    ? <Input value={deptEditAd} onChange={e=>setDeptEditAd(e.target.value.toUpperCase())} style={{width:"100%"}} onKeyDown={e=>e.key==="Enter"&&duzenlemeKaydet(i)} />
                    : <span style={{fontWeight:600}}>{dept.ad}</span>
                  }
                </td>
                <td>
                  {deptEditIdx===i
                    ? <Input value={deptEditAciklama} onChange={e=>setDeptEditAciklama(e.target.value)} style={{width:"100%"}} placeholder="Açıklama..." onKeyDown={e=>e.key==="Enter"&&duzenlemeKaydet(i)} />
                    : <span style={{color:"var(--text-secondary)",fontSize:12}}>{dept.aciklama||<span style={{color:"var(--text-tertiary)"}}>—</span>}</span>
                  }
                </td>
                <td style={{textAlign:"center"}}>
                  <span style={{fontSize:12,color:"var(--text-tertiary)"}}>{personeller.filter(p=>p.departman===dept.ad).length}</span>
                </td>
                {canEdit && <td>
                  {deptEditIdx===i
                    ? <div style={{display:"flex",gap:4}}>
                        <Btn primary style={{padding:"3px 8px",fontSize:11}} onClick={()=>duzenlemeKaydet(i)}>✓</Btn>
                        <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>setDeptEditIdx(null)}>✕</Btn>
                      </div>
                    : <div style={{display:"flex",gap:4}}>
                        <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>{setDeptEditIdx(i);setDeptEditAd(dept.ad);setDeptEditAciklama(dept.aciklama||"");}}>✏️</Btn>
                        <Btn danger style={{padding:"3px 8px",fontSize:11}} onClick={()=>sil(dept)}>🗑️</Btn>
                      </div>
                  }
                </td>}
              </tr>
            ))}</tbody>
          </table>
        </div>
      </div>
    );
  }

  if(subMenu==="Görevler") {
    // State'ler Tanimlar başında tanımlı

    const kaydet = (liste) => { setGorevlerState(liste); saveGorevler(liste); };

    // Seçili departmandaki görevler — sıralı
    const deptGorevler = gorevler
      .filter(g=>g.departman===seciliDept)
      .sort((a,b)=>(a.siraNo||99)-(b.siraNo||99));

    // Seçili departmanda bir sonraki sıra no
    const sonrakiSira = deptGorevler.length > 0 ? Math.max(...deptGorevler.map(g=>g.siraNo||0))+1 : 1;

    const ekle = () => {
      const v = yeniGorevAd.trim();
      if(!v) return;
      if(gorevler.find(g=>g.departman===seciliDept && g.ad===v)) { alert("Bu görev zaten var!"); return; }
      kaydet([...gorevler, {departman:seciliDept, ad:v, aciklama:yeniGorevAciklama.trim(), kademe:yeniGorevKademe, siraNo:sonrakiSira}]);
      setYeniGorevAd(""); setYeniGorevAciklama(""); setYeniGorevKademe("Eleman");
    };

    const duzenlemeKaydet = (g) => {
      const v = gorevEditAd.trim();
      if(!v) return;
      kaydet(gorevler.map(x=>x===g?{...x, ad:v, aciklama:gorevEditAciklama.trim(), kademe:gorevEditKademe, siraNo:gorevEditSira}:x));
      setGorevEditIdx(null);
    };

    const sil = (g) => {
      const kullanan = personeller.filter(p=>p.gorev===g.ad && p.departman===g.departman);
      if(kullanan.length>0) {
        alert(`"${g.ad}" görevine ait ${kullanan.length} personel var. Silmeden önce bu kişilerin görevini değiştirin.`);
        return;
      }
      const hareketler = (() => { try { const v=localStorage.getItem("pdks_hareketler"); return v?JSON.parse(v):[]; } catch{return[];} })();
      const hareketKullanan = hareketler.filter(h=>h.gorev===g.ad && h.departman===g.departman);
      if(hareketKullanan.length>0) {
        alert(`"${g.ad}" görevi ${hareketKullanan.length} personel hareketinde kayıtlı.\nSilmeden önce bu kayıtları temizleyin.`);
        return;
      }
      if(!confirm(`"${g.ad}" görevini silmek istiyor musunuz?`)) return;
      kaydet(gorevler.filter(x=>x!==g));
    };

    const siraDegistir = (g, yon) => {
      const idx = deptGorevler.indexOf(g);
      const diger = deptGorevler[idx+yon];
      if(!diger) return;
      const yeni = gorevler.map(x=>{
        if(x===g) return {...x, siraNo:diger.siraNo};
        if(x===diger) return {...x, siraNo:g.siraNo};
        return x;
      });
      kaydet(yeni);
    };

    return (
      <div>
        {/* Departman seçici */}
        <div style={{display:"flex",gap:12,marginBottom:16,alignItems:"flex-end",flexWrap:"wrap"}}>
          <div>
            <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4,fontWeight:600}}>DEPARTMAN</div>
            <Select value={seciliDept} onChange={e=>setSeciliDept(e.target.value)} style={{width:220}}>
              {getDepartmanlar().map(d=><option key={d.ad} value={d.ad}>{d.ad}</option>)}
            </Select>
          </div>
          <div style={{fontSize:12,color:"var(--text-tertiary)"}}>
            {deptGorevler.length} görev tanımlı
          </div>
        </div>

        {/* Yeni görev ekle */}
        {canEdit && (
          <div style={{display:"flex",gap:8,marginBottom:14,alignItems:"flex-end",flexWrap:"wrap",padding:"12px 14px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:8}}>
            <div>
              <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>Görev Adı</div>
              <Input value={yeniGorevAd} onChange={e=>setYeniGorevAd(e.target.value)} placeholder="ör. Animasyon Şefi" style={{width:200}} onKeyDown={e=>e.key==="Enter"&&ekle()} />
            </div>
            <div>
              <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>Kademe</div>
              <Select value={yeniGorevKademe} onChange={e=>setYeniGorevKademe(e.target.value)} style={{width:150}}>
                {KADEME_LISTESI.map(k=><option key={k}>{k}</option>)}
              </Select>
            </div>
            <div style={{flex:1}}>
              <div style={{fontSize:11,color:"var(--text-secondary)",marginBottom:4}}>Açıklama (opsiyonel)</div>
              <Input value={yeniGorevAciklama} onChange={e=>setYeniGorevAciklama(e.target.value)} placeholder="Görev açıklaması..." onKeyDown={e=>e.key==="Enter"&&ekle()} />
            </div>
            <Btn primary onClick={ekle}>Ekle</Btn>
          </div>
        )}

        {/* Görev listesi */}
        <div className="pdks-card">
          {deptGorevler.length===0
            ? <div style={{padding:24,textAlign:"center",color:"var(--text-tertiary)"}}>Bu departmana görev eklenmemiş</div>
            : <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
                <thead><tr>
                  <th style={{width:36}}>Sıra</th>
                  <th>Görev Adı</th>
                  <th style={{width:140}}>Kademe</th>
                  <th>Açıklama</th>
                  <th style={{width:50}}>Personel</th>
                  {canEdit && <th style={{width:140}}>İşlem</th>}
                </tr></thead>
                <tbody>{deptGorevler.map((g,i)=>(
                  <tr key={i}>
                    <td style={{textAlign:"center"}}>
                      <div style={{display:"flex",flexDirection:"column",gap:1,alignItems:"center"}}>
                        <span style={{fontWeight:600,fontSize:12}}>{g.siraNo||i+1}</span>
                        {canEdit && <div style={{display:"flex",gap:2}}>
                          <button onClick={()=>siraDegistir(g,-1)} disabled={i===0} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-tertiary)",fontSize:10,padding:"0 2px",opacity:i===0?0.3:1}}>▲</button>
                          <button onClick={()=>siraDegistir(g,1)} disabled={i===deptGorevler.length-1} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-tertiary)",fontSize:10,padding:"0 2px",opacity:i===deptGorevler.length-1?0.3:1}}>▼</button>
                        </div>}
                      </div>
                    </td>
                    <td>
                      {gorevEditIdx===i
                        ? <div style={{display:"flex",gap:6,alignItems:"center"}}>
                            <Input value={gorevEditAd} onChange={e=>setGorevEditAd(e.target.value)} style={{flex:1}} onKeyDown={e=>e.key==="Enter"&&duzenlemeKaydet(g)} />
                            <input type="number" value={gorevEditSira} onChange={e=>setGorevEditSira(+e.target.value)} style={{width:50,padding:"7px 6px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:13}} />
                          </div>
                        : <span style={{fontWeight:500}}>{g.ad}</span>
                      }
                    </td>
                    <td>
                      {gorevEditIdx===i
                        ? <Select value={gorevEditKademe} onChange={e=>setGorevEditKademe(e.target.value)}>
                            {KADEME_LISTESI.map(k=><option key={k}>{k}</option>)}
                          </Select>
                        : <span style={{background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:20,padding:"2px 10px",fontSize:11,fontWeight:500}}>{g.kademe||"—"}</span>
                      }
                    </td>
                    <td>
                      {gorevEditIdx===i
                        ? <Input value={gorevEditAciklama} onChange={e=>setGorevEditAciklama(e.target.value)} placeholder="Açıklama..." onKeyDown={e=>e.key==="Enter"&&duzenlemeKaydet(g)} />
                        : <span style={{color:"var(--text-secondary)",fontSize:12}}>{g.aciklama||<span style={{color:"var(--text-tertiary)"}}>—</span>}</span>
                      }
                    </td>
                    <td style={{textAlign:"center",fontSize:12,color:"var(--text-tertiary)"}}>
                      {personeller.filter(p=>p.gorev===g.ad&&p.departman===g.departman).length}
                    </td>
                    {canEdit && <td>
                      {gorevEditIdx===i
                        ? <div style={{display:"flex",gap:4}}>
                            <Btn primary style={{padding:"3px 8px",fontSize:11}} onClick={()=>duzenlemeKaydet(g)}>✓ Kaydet</Btn>
                            <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>setGorevEditIdx(null)}>✕</Btn>
                          </div>
                        : <div style={{display:"flex",gap:4}}>
                            <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>{setGorevEditIdx(i);setGorevEditAd(g.ad);setGorevEditAciklama(g.aciklama||"");setGorevEditSira(g.siraNo||i+1);setGorevEditKademe(g.kademe||"Eleman");}}>✏️</Btn>
                            <Btn danger style={{padding:"3px 8px",fontSize:11}} onClick={()=>sil(g)}>🗑️</Btn>
                          </div>
                      }
                    </td>}
                  </tr>
                ))}</tbody>
              </table>
          }
        </div>
      </div>
    );
  }

  if(subMenu==="Resmi Tatiller") {
    const tatilKaydet = () => {
      if(!rtForm.tarih || !rtForm.ad) { alert("Tarih ve Ad zorunludur."); return; }
      if(rtEdit) {
        saveTatiller(tatiller.map(t=>t===rtEdit ? rtForm : t));
      } else {
        if(tatiller.find(t=>t.tarih===rtForm.tarih)) { alert("Bu tarihte zaten tatil var!"); return; }
        saveTatiller([...tatiller, rtForm].sort((a,b)=>a.tarih.split(".").reverse().join("").localeCompare(b.tarih.split(".").reverse().join(""))));
      }
      setRtModal(false); setRtEdit(null); setRtForm({tarih:"", ad:"", aciklama:"", katsayi:2});
    };
    const tatilSil = (t) => {
      if(!confirm(`"${t.ad}" (${t.tarih}) silinsin mi?`)) return;
      saveTatiller(tatiller.filter(x=>x!==t));
    };

    // Yıllara göre grupla
    const yillar = [...new Set(tatiller.map(t=>t.tarih?.split(".")[2]).filter(Boolean))].sort((a,b)=>b-a);
    const buYil = new Date().getFullYear();

    return (
      <div>
        {/* Modal */}
        {rtModal && (
          <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:300}}>
            <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:440}}>
              <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <span style={{fontWeight:600,fontSize:15}}>{rtEdit?"Tatil Düzenle":"Yeni Resmi Tatil"}</span>
                <button onClick={()=>{setRtModal(false);setRtEdit(null);setRtForm({tarih:"",ad:"",aciklama:"",katsayi:2});}} style={{background:"none",border:"none",cursor:"pointer",color:"var(--text-secondary)",fontSize:18}}>✕</button>
              </div>
              <div style={{padding:20,display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
                <FormRow label="Tarih (GG.AA.YYYY)">
                  <DateInput value={rtForm.tarih} onChange={e=>setRtForm(p=>({...p,tarih:e.target.value}))} />
                </FormRow>
                <FormRow label="Mesai Katsayısı">
                  <div style={{display:"flex",alignItems:"center",gap:8}}>
                    <Input type="number" value={rtForm.katsayi} onChange={e=>setRtForm(p=>({...p,katsayi:+e.target.value}))} style={{width:80}} />
                    <span style={{fontSize:11,color:"var(--text-secondary)"}}>× normal mesai</span>
                  </div>
                </FormRow>
                <FormRow label="Tatil Adı" style={{gridColumn:"1/-1"}}>
                  <Input value={rtForm.ad} onChange={e=>setRtForm(p=>({...p,ad:e.target.value}))} placeholder="ör. Yılbaşı" />
                </FormRow>
                <FormRow label="Açıklama" style={{gridColumn:"1/-1"}}>
                  <Input value={rtForm.aciklama} onChange={e=>setRtForm(p=>({...p,aciklama:e.target.value}))} placeholder="Opsiyonel açıklama" />
                </FormRow>
                <div style={{gridColumn:"1/-1",padding:"10px 14px",background:"var(--input-bg)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
                  💡 Katsayı <strong>{rtForm.katsayi}</strong> ise bu günde çalışan personele normal mesainin <strong>{rtForm.katsayi}x</strong>'i ödenir.
                </div>
              </div>
              <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
                <Btn onClick={()=>{setRtModal(false);setRtEdit(null);setRtForm({tarih:"",ad:"",aciklama:"",katsayi:2});}}>İptal</Btn>
                <Btn primary onClick={tatilKaydet}>Kaydet</Btn>
              </div>
            </div>
          </div>
        )}

        {/* Üst bar */}
        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16,flexWrap:"wrap",gap:8}}>
          <div>
            <div style={{fontSize:14,fontWeight:600,color:"var(--text-primary)"}}>Resmi Tatil Takvimi</div>
            <div style={{fontSize:12,color:"var(--text-secondary)",marginTop:2}}>
              {tatiller.length} kayıt · {yillar.length} yıl ({yillar.join(", ")})
            </div>
          </div>
          <div style={{display:"flex",gap:8}}>
            {/* Yeni yıla kopyala */}
            {canEdit && yillar.length > 0 && (
              <Btn onClick={()=>{
                const enSonYil = yillar[0];
                const hedefYil = String(+enSonYil + 1);
                if(tatiller.some(t=>t.tarih?.endsWith(hedefYil))) {
                  alert(`${hedefYil} yılı için zaten tatil tanımlı.`); return;
                }
                if(!confirm(`${enSonYil} yılı tatillerini ${hedefYil} yılına kopyalayalım mı? Tarihler otomatik güncellenir.`)) return;
                const yeniTatiller = tatiller
                  .filter(t=>t.tarih?.endsWith(enSonYil))
                  .map(t=>{
                    const [g,a,y]=t.tarih.split(".");
                    return {...t, tarih:`${g}.${a}.${hedefYil}`};
                  });
                saveTatiller([...tatiller,...yeniTatiller].sort((a,b)=>a.tarih.split(".").reverse().join("").localeCompare(b.tarih.split(".").reverse().join(""))));
              }} style={{fontSize:12}}>
                📋 {yillar[0]} → {+yillar[0]+1} Kopyala
              </Btn>
            )}
            {canEdit && <Btn primary onClick={()=>{setRtForm({tarih:"",ad:"",aciklama:"",katsayi:2});setRtEdit(null);setRtModal(true);}}>Yeni Tatil Ekle</Btn>}
          </div>
        </div>

        {/* Yıllara göre gruplu listeler */}
        {yillar.length === 0 && (
          <div style={{padding:32,textAlign:"center",color:"var(--text-tertiary)"}}>Henüz tatil eklenmemiş</div>
        )}
        {yillar.map(yil => {
          const yilTatilleri = tatiller.filter(t=>t.tarih?.endsWith(yil));
          const isCurrentYear = yil === String(buYil);
          const isOpen = rtAcikYillar.has(yil);
          return (
            <div key={yil} style={{marginBottom:8,border:"1px solid var(--grid-line)",borderRadius:8,overflow:"hidden"}}>
              {/* Yıl başlığı — tıklanabilir */}
              <div onClick={()=>setRtAcikYillar(prev=>{const s=new Set(prev); s.has(yil)?s.delete(yil):s.add(yil); return s;})}
                style={{display:"flex",alignItems:"center",gap:10,padding:"10px 16px",background:isCurrentYear?"var(--th-bg)":"var(--input-bg)",cursor:"pointer",userSelect:"none"}}>
                <span style={{fontSize:14,fontWeight:700,color:isCurrentYear?"#fff":"var(--text-primary)"}}>
                  📅 {yil}
                </span>
                {isCurrentYear && <span style={{fontSize:10,background:"rgba(255,255,255,0.2)",color:"#fff",padding:"1px 8px",borderRadius:20,fontWeight:600}}>Bu Yıl</span>}
                {(() => {
                  const toplamGun = yilTatilleri.reduce((acc,t)=>acc+((t.katsayi||2)-1),0);
                  return (
                    <span style={{fontSize:12,color:isCurrentYear?"rgba(255,255,255,0.7)":"var(--text-secondary)",flex:1}}>
                      {yilTatilleri.length} gün · <strong>{toplamGun}</strong> ekstra ödeme günü
                    </span>
                  );
                })()}
                <span style={{fontSize:11,color:isCurrentYear?"rgba(255,255,255,0.7)":"var(--text-tertiary)"}}>{isOpen?"▲":"▼"}</span>
              </div>

              {/* Tatil listesi */}
              {isOpen && (
                <table className="pdks-table" style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
                  <thead><tr>
                    <th style={{width:110}}>Tarih</th>
                    <th>Tatil Adı</th>
                    <th>Açıklama</th>
                    <th style={{width:110,textAlign:"center"}}>Mesai Katsayısı</th>
                    {canEdit && <th style={{width:80}}>İşlem</th>}
                  </tr></thead>
                  <tbody>{yilTatilleri.map((t,i)=>(
                    <tr key={i}>
                      <td><span style={{background:"#FCEBEB",color:"#A32D2D",padding:"3px 10px",borderRadius:6,fontSize:12,fontWeight:600}}>{t.tarih}</span></td>
                      <td style={{fontWeight:500}}>{t.ad}</td>
                      <td style={{color:"var(--text-secondary)",fontSize:12}}>{t.aciklama||"—"}</td>
                      <td style={{textAlign:"center"}}>
                        <span style={{background:"#FAEEDA",color:"#854F0B",padding:"3px 12px",borderRadius:20,fontSize:12,fontWeight:700}}>{t.katsayi||2}x</span>
                      </td>
                      {canEdit && <td><div style={{display:"flex",gap:5}}>
                        <Btn style={{padding:"3px 8px",fontSize:11}} onClick={()=>{setRtForm({...t});setRtEdit(t);setRtModal(true);}}>✏️</Btn>
                        <Btn danger style={{padding:"3px 8px",fontSize:11}} onClick={()=>tatilSil(t)}>🗑️</Btn>
                      </div></td>}
                    </tr>
                  ))}</tbody>
                </table>
              )}
            </div>
          );
        })}

        <div style={{marginTop:12,padding:"10px 14px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
          ℹ️ Aylık puantajda bu tarihlere shift girilmiş personeller <strong>Resmi Tatil Çalışması</strong> olarak işaretlenecek ve katsayıya göre hesaplanacaktır.
        </div>
      </div>
    );
  }

  if(subMenu==="Firma Parametreleri") {
    const FRow = ({label, children, col=false}) => (
      <div style={{display:"flex",alignItems:col?"flex-start":"center",gap:12,padding:"9px 0",borderBottom:"1px solid var(--grid-line)"}}>
        <span style={{minWidth:220,fontSize:13,color:"var(--text-secondary)",flexShrink:0}}>{label}</span>
        <div style={{flex:1}}>{children}</div>
      </div>
    );
    const FInput = ({fkey, placeholder="", type="text", style={}}) => (
      <input type={type} value={firmaParams[fkey]||""} onChange={fp(fkey)}
        placeholder={placeholder}
        style={{width:"100%",padding:"6px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:13,...style}} />
    );
    const FCheck = ({fkey, label}) => (
      <label style={{display:"flex",alignItems:"center",gap:8,cursor:"pointer",fontSize:13}}>
        <input type="checkbox" checked={!!firmaParams[fkey]} onChange={fp(fkey)} />
        {label}
      </label>
    );

    return (
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:24}}>
        {/* SOL — Firma Parametreleri */}
        <div>
          <div style={{fontWeight:600,fontSize:13,color:"var(--text-tertiary)",marginBottom:8,letterSpacing:.05}}>FİRMA BİLGİLERİ</div>
          <div className="pdks-card" style={{padding:"0 16px"}}>
            <FRow label="Firma No"><FInput fkey="firmaNo" placeholder="06" /></FRow>
            <FRow label="Şirket Ünvanı"><FInput fkey="sirketUnvani" placeholder="FLORA BEACH RESORT" /></FRow>
            <FRow label="Cihaz IP Adresi"><FInput fkey="cihazIpAdresi" placeholder="10.4.0.6" /></FRow>
            <FRow label="Cihaz IP Açıklaması"><FInput fkey="cihazIpAciklama" placeholder="Giriş cihazı" /></FRow>
          </div>

          <div style={{fontWeight:600,fontSize:13,color:"var(--text-tertiary)",margin:"16px 0 8px",letterSpacing:.05}}>PUANTAJ AYARLARI</div>
          <div className="pdks-card" style={{padding:"0 16px"}}>
            <FRow label="Puantaj Çalışma Yazısı"><FInput fkey="puantajCalismaYazisi" placeholder="1" style={{width:80}} /></FRow>
            <FRow label="Maks. Değişiklik Günü"><FInput fkey="maxDegisiklikGunu" type="number" style={{width:80}} /></FRow>
            <FRow label="Puantaj Ücretli İzin Yazısı"><FInput fkey="puantajUcretliIzinYazisi" placeholder="Üİ" style={{width:80}} /></FRow>
            <FRow label="Puantaj Ücretsiz İzin Yazısı"><FInput fkey="puantajUcretsizIzinYazisi" placeholder="ÜS" style={{width:80}} /></FRow>
            <FRow label="Yol Ücreti Hesapla"><FCheck fkey="yolUcretiHesapla" label="" /></FRow>
            <FRow label="Tatil Hesapla"><FCheck fkey="tatilHesapla" label="" /></FRow>
            <FRow label="Puantaj Tatil Rengi">
              <div style={{display:"flex",gap:8,alignItems:"center"}}>
                <input type="color" value={firmaParams.puantajTatilRengi||"#185FA5"} onChange={fp("puantajTatilRengi")}
                  style={{width:40,height:32,border:"none",cursor:"pointer",background:"none"}} />
                <span style={{fontSize:12,color:"var(--text-tertiary)",fontFamily:"monospace"}}>{firmaParams.puantajTatilRengi}</span>
              </div>
            </FRow>
            <FRow label="Departman Puantaj Yetkisi"><FCheck fkey="departmanPuantajYetkisi" label="" /></FRow>
            <FRow label="Puantaj Toplamı 30 Gün Alsın"><FCheck fkey="puantajToplami30GunAlsin" label="" /></FRow>
            <FRow label="11 Saat Öncesi Shift Atama Onayı">
              <div style={{display:"flex",gap:16}}>
                {["yok","onay","engelle"].map(v=>(
                  <label key={v} style={{display:"flex",alignItems:"center",gap:5,cursor:"pointer",fontSize:13}}>
                    <input type="radio" name="onbirsaat" checked={firmaParams.onbirsaatOncesiShiftAtamaOnayi===v} onChange={()=>saveFirmaParams({...firmaParams,onbirsaatOncesiShiftAtamaOnayi:v})} />
                    {v.charAt(0).toUpperCase()+v.slice(1)}
                  </label>
                ))}
              </div>
            </FRow>
            <FRow label="Atanan İzinler Onaydan Geçsin"><FCheck fkey="atanenIzinlerOnaydan" label="" /></FRow>
            <FRow label="Sabit Tatil Günleri">
              <div style={{display:"flex",gap:16}}>
                <label style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer",fontSize:13}}>
                  <input type="checkbox" checked={!!firmaParams.sabitTatilGunleri?.cumartesi}
                    onChange={e=>saveFirmaParams({...firmaParams,sabitTatilGunleri:{...firmaParams.sabitTatilGunleri,cumartesi:e.target.checked}})} />
                  Cumartesi
                </label>
                <label style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer",fontSize:13}}>
                  <input type="checkbox" checked={!!firmaParams.sabitTatilGunleri?.pazar}
                    onChange={e=>saveFirmaParams({...firmaParams,sabitTatilGunleri:{...firmaParams.sabitTatilGunleri,pazar:e.target.checked}})} />
                  Pazar
                </label>
              </div>
            </FRow>
            <FRow label="Departman İzin Giriş Yetkisi"><FCheck fkey="departmanIzinGirisYetkisi" label="" /></FRow>
          </div>
        </div>

        {/* SAĞ — Bordro Entegrasyon */}
        <div>
          <div style={{fontWeight:600,fontSize:13,color:"var(--text-tertiary)",marginBottom:8,letterSpacing:.05}}>BORDRO ENTEGRASYON PARAMETRELERİ</div>
          <div className="pdks-card" style={{padding:"0 16px"}}>
            <FRow label="Bordro Programı">
              <Select value={firmaParams.bordroProgrami||"Logo"} onChange={fp("bordroProgrami")} style={{width:200}}>
                {["Logo","Mikro","IK360","Nebim","SAP","Diğer"].map(p=><option key={p}>{p}</option>)}
              </Select>
            </FRow>
            <FRow label="Çalışma Alanı"><FInput fkey="calismaAlani" placeholder="002" /></FRow>
            <FRow label="Bordro Firma No"><FInput fkey="bordroFirmaNo" placeholder="07" /></FRow>
            <FRow label="Connection String">
              <textarea value={firmaParams.connectionString||""} onChange={fp("connectionString")}
                placeholder="Data Source=10.5.0.144;Initial Catalog=..."
                rows={3}
                style={{width:"100%",padding:"6px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:12,fontFamily:"monospace",resize:"vertical"}} />
            </FRow>
          </div>

          <div style={{marginTop:16,padding:"12px 16px",background:"var(--input-bg)",border:"1px solid var(--grid-line)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
            ℹ️ Bordro entegrasyon alanları kaydedilir ancak aktif bağlantı kurulmaz. İleride bordro aktarım modülü bu parametreleri kullanacaktır.
          </div>

          <div style={{marginTop:16,display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn onClick={()=>saveFirmaParams(FIRMA_VARSAYILAN)}>Varsayılanlara Dön</Btn>
            <Btn primary onClick={()=>alert("✓ Firma parametreleri kaydedildi.")}>Kaydet</Btn>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div style={{color:"var(--text-secondary)",fontSize:13,padding:20,textAlign:"center"}}>
      Sol menüden bir tanım seçin.
    </div>
  );
};

// ─── RAPORLAR ─────────────────────────────────────────────────────────────────
const Raporlar = ({subMenu}) => (
  <div>
    <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16,marginBottom:16}}>
      <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8,padding:16}}>
        <div style={{fontSize:13,fontWeight:500,marginBottom:12}}>Rapor Türü</div>
        {["İzin Raporları","Hatalı Shift Hareketleri","Doğum Günü Listesi","Mesai Toplamları Raporu","Personel Shift Listesi","Bütçe Raporu","İki Shift Arası Saat Farkı Raporu","Off Çalışması Raporu"].map(r=>(
          <label key={r} style={{display:"flex",alignItems:"center",gap:8,fontSize:13,cursor:"pointer",padding:"5px 0",borderBottom:"0.5px solid var(--grid-line)"}}>
            <input type="radio" name="raporTipi" defaultChecked={r==="Personel Shift Listesi"} /> {r}
          </label>
        ))}
      </div>
      <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8,padding:16}}>
        <div style={{fontSize:13,fontWeight:500,marginBottom:12}}>Parametreler</div>
        <FormRow label="Departman"><Select><option>Tüm Departmanlar</option>{getDepartmanlar().map(d=><option key={d.ad} value={d.ad}>{d.ad}</option>)}</Select></FormRow>
        <FormRow label="Çalışma Grubu"><Select><option>TUMU</option><option>NOR. ÇL.</option><option>STJ.</option></Select></FormRow>
        <FormRow label="Tarih Aralığı"><div style={{display:"flex",gap:8}}><input type="month" defaultValue="2026-05" style={{flex:1,padding:"7px 10px",border:"0.5px solid var(--input-border)",borderRadius:8,background:"var(--input-bg)",fontSize:13,color:"var(--text-primary)"}} /></div></FormRow>
        <FormRow label="Format">
          <Select><option>Excel (.xlsx)</option><option>PDF</option><option>CSV</option></Select>
        </FormRow>
        <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
          {[["Mesai Toplamlarını Göster",false],["İzin Bakiyeleri Yüklensin",false],["Servis-Durak Bilgisi Yükle",false]].map(([l,d])=>(
            <label key={l} style={{display:"flex",alignItems:"center",gap:6,fontSize:12,cursor:"pointer",color:"var(--text-secondary)"}}><input type="checkbox" defaultChecked={d}/> {l}</label>
          ))}
        </div>
        <div style={{marginTop:16}}><Btn primary style={{width:"100%",justifyContent:"center"}}>📥 Rapor İndir</Btn></div>
      </div>
    </div>
  </div>
);

// ─── MAIN APP ────────────────────────────────────────────────────────────────

// PDKSApp: Kullanıcı giriş yaptıktan sonra çalışır — her kullanıcı için sıfırdan init
function PDKSApp({kullanici, onLogout}) {
  const uid = kullanici.id;

  // ─── Uygulama state — uid bazlı localStorage'dan init ───
  const [personeller, setPersonellerRaw] = useState(() => {
    try {
      const v = localStorage.getItem("pdks_personeller");
      return v ? JSON.parse(v) : initPersonel;
    } catch { return initPersonel; }
  });
  const setPersoneller = (val) => {
    const next = typeof val === "function" ? val(personeller) : val;
    setPersonellerRaw(next);
    try { localStorage.setItem("pdks_personeller", JSON.stringify(next)); } catch {}
  };
  const [activeMenu, setActiveMenu] = useState(() => lsGet(uid,"activeMenu","hatali"));
  const [activeSubMenu, setActiveSubMenu] = useState(null);
  const [openDropdown, setOpenDropdown] = useState(null);

  // Dışarı tıklayınca menüyü kapat
  useEffect(() => {
    if(!openDropdown) return;
    const handler = (e) => {
      if(!e.target.closest('.topbar-dropdown')) setOpenDropdown(null);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [openDropdown]);
  const [selectedPersonel, setSelectedPersonel] = useState(null);
  const [showAddModal, setShowAddModal] = useState(false);
  const [showExcelImport, setShowExcelImport] = useState(false);
  const [showTopluIzin, setShowTopluIzin] = useState(false);
  const [searchText, setSearchText] = useState("");
  const [deptFilter, setDeptFilter] = useState("TÜMÜ");
  const [durumFilter, setDurumFilter] = useState("TÜMÜ");
  const [darkMode, setDarkMode] = useState(() => lsGet(uid,"darkMode",true));
  const [aciklamaGizle, setAciklamaGizle] = useState(() => lsGet(uid,"aciklamaGizle",false));
  const [hataliHiddenCols, setHataliHiddenCols] = useState(() => new Set(lsGet(uid,"hataliHidden",[])));
  const [onayTick, setOnayTick] = useState(0); // onay listesi yenilemek için
  // Alan izinleri — PDKSApp seviyesinde tutulur, tüm bileşenlere prop geçilir
  const [alanIzinleri, setAlanIzinleriApp] = useState(() => getAlanIzinleri());
  const setAlanIzni = (key, goster) => {
    setAlanIzinleriApp(prev => {
      const yeni = {...prev, [key]: {...prev[key], goster}};
      saveAlanIzinleri(yeni);
      return yeni;
    });
  };

  // Değişiklikleri kaydet
  useEffect(() => { lsSet(uid,"darkMode",darkMode); }, [darkMode]);
  useEffect(() => { lsSet(uid,"aciklamaGizle",aciklamaGizle); }, [aciklamaGizle]);
  useEffect(() => { lsSet(uid,"hataliHidden",[...hataliHiddenCols]); }, [hataliHiddenCols]);
  useEffect(() => { lsSet(uid,"activeMenu",activeMenu); }, [activeMenu]);

  const handleLogout = () => {
    localStorage.removeItem("pdks_aktif_kullanici");
    onLogout();
  };

  // Anlık hareketler — TUM_HAREKETLER'den bugünkü, kullanıcının departmanlarına göre filtreli
  const liveFeed = TUM_HAREKETLER
    .filter(h => {
      if(kullanici?.yetki !== "admin" && !gorebilirMi(kullanici, h.departman)) return false;
      return h.tarih === BUGUN_TARIH;
    })
    .map(h => ({
      saat: h.gGiris || "—",
      tip: h.gCikis ? "ÇIKIŞ" : (h.gGiris ? "GİRİŞ" : "—"),
      ad: `${h.ad} ${h.soyad}`,
      departman: h.departman,
      hatali: h.hatali,
    }))
    .slice(0, 20);

  const emptyP = {id:Date.now(),sicil:"",tc:"",ad:"",soyad:"",departman:DEPARTMANLAR[0],gorev:GOREVLER[0],calismaGrubu:"NOR. ÇL.",isGiris:"",istenCikis:"",durum:"Çalışıyor",telefon:"",dogumTarihi:"",kanGrubu:"",maas:0,cihazNo:"",dolapNo:"",lojmanNo:"",sgkNo:"",sskTar:"",sirketGiris:"",devamKontrol:"Yapılacak",servis:"",durak:"",hesDoku:"",bordroSicil:"",ogrenim:"",acilGrup:"",uiDevir:0,yiDevir:0,notlar:""};

  const savePersonel = (updated) => {
    if(updated === null) {
      // Silme sinyali — selectedPersonel'i sil
      if(selectedPersonel) {
        setPersoneller(prev=>prev.filter(p=>p.id!==selectedPersonel.id));
      }
      setSelectedPersonel(null);
      setShowAddModal(false);
      return;
    }
    if(personeller.find(p=>p.id===updated.id)) {
      setPersoneller(prev=>prev.map(p=>p.id===updated.id?updated:p));
    } else {
      setPersoneller(prev=>[...prev,{...updated,id:Date.now()}]);
    }
    setSelectedPersonel(null);
    setShowAddModal(false);
  };

  const filteredPersonel = personeller.filter(p=>{
    const q = searchText.toLowerCase();
    if(q && !`${p.ad} ${p.soyad} ${p.departman} ${p.gorev} ${p.sicil}`.toLowerCase().includes(q)) return false;
    if(deptFilter!=="TÜMÜ" && p.departman!==deptFilter) return false;
    if(durumFilter!=="TÜMÜ" && p.durum!==durumFilter) return false;
    // Yetki filtresi — kullanıcı sadece kendi departmanlarını görür
    if(!gorebilirMi(kullanici, p.departman)) return false;
    return true;
  });

  // Aktif ekrana göre düzenleme yetkisi
  const readOnly = !duzenleyebilirMi(kullanici, activeMenu);

  const tanımlarMenu = ["Shiftler","İzinler","Departmanlar","Görevler","Bölümler","Kullanıcılar","Resmi Tatiller","Departman Bütçeleri","Acil Durum Grubu","Servis Yönetimi","Durak Yönetimi","Eğitim Tanımları","Firma Parametreleri"];
  const esitlemeMenu = ["Personelleri Cihaza Aktar","Bordro Personellerini Oku","Cihaz Hareketlerini Eşitle","Cihazlar Arası Aktarım","Cihazlar Arası Kontrol","Excel Personel Listesi Al"];
  const raporlarMenu = ["İzin Raporları","Hatalı Shift Hareketleri","Doğum Günü Listesi","Mesai Toplamları Raporu","Personel Shift Listesi","Bütçe Raporu","İki Shift Arası Saat Farkı Raporu","Off Çalışması Raporu"];
  const bakimMenu = ["G/Ç Otomatik Doldur","Cihaz Verilerini Yedekle","Toplu İzin Girişi","Log Kayıtları","Ayarlar","Otomatik Çalışma Planı","Mesai-İzin Bağlantıları","Personel Eğitim Bağlantıları","Excel Puantaj Aktarımı","Excel Mesai Aktarımı"];

  // Kullanıcı yetkisine göre üst menü — kullanici için sadece görebilenler
  const topMenuItems = kullanici.yetki==="admin"
    ? [["Tanımlar",tanımlarMenu],["Eşitleme İşlemleri",esitlemeMenu],["Raporlar",raporlarMenu],["Bakım İşlemleri",bakimMenu]]
    : []; // kullanici üst menü göremez

  const pageTitle = {hatali:"Hatalı Shift Hareketleri / Anlık Rapor",personel:"Personel Listesi",giris:"Personel Hareketleri",puantaj:"Aylık Puantaj",shift:"Shift Atamaları",tanimlar:"Tanımlar",raporlar:"Raporlar",bakim:"Bakım İşlemleri"}[activeMenu]||"";

  return (
    <div style={{display:"flex",flexDirection:"column",height:"100vh",minHeight:700,fontFamily:"var(--font-sans)",background:"var(--page-bg)",color:"var(--text-primary)"}}>
      <GlobalStyle dark={darkMode} />
      {/* Top bar */}
      <div style={{background:"var(--topbar-bg)",color:"#fff",display:"flex",alignItems:"center",gap:0,padding:"0 12px",minHeight:44,flexShrink:0,position:"relative",zIndex:50}}>
        <span style={{fontSize:13,fontWeight:500,marginRight:20,opacity:.9}}>TimeCore</span>
        {topMenuItems.map(([label,menu])=>(
          <div key={label} style={{position:"relative"}}>
            <button onClick={()=>setOpenDropdown(openDropdown===label?null:label)} style={{padding:"10px 14px",background:"none",border:"none",color:"#fff",fontSize:13,cursor:"pointer",fontFamily:"var(--font-sans)",opacity:openDropdown===label?1:.85}}>{label}</button>
            {openDropdown===label && (
              <div className="topbar-dropdown" style={{position:"absolute",top:"100%",left:0,background:darkMode?"#1e2433":"#fff",border:`1px solid ${darkMode?"rgba(255,255,255,0.1)":"#ddd"}`,borderRadius:6,boxShadow:"0 4px 16px rgba(0,0,0,.25)",minWidth:220,zIndex:100}}>
                {menu.map(item=>(
                  <div key={item} onClick={()=>{setActiveMenu(label==="Tanımlar"?"tanimlar":label==="Raporlar"?"raporlar":"bakim");setActiveSubMenu(item);setOpenDropdown(null);}} style={{padding:"9px 16px",fontSize:13,cursor:"pointer",color:darkMode?"#f1f5f9":"#333",borderBottom:`1px solid ${darkMode?"rgba(255,255,255,0.06)":"#f0f0f0"}`}} onMouseEnter={e=>e.currentTarget.style.background=darkMode?"#253352":"#f5f5f5"} onMouseLeave={e=>e.currentTarget.style.background=""}>{item}</div>
                ))}
              </div>
            )}
          </div>
        ))}
        <div style={{marginLeft:"auto",display:"flex",alignItems:"center",gap:6}}>
          <span style={{fontSize:11,opacity:.7}}>{darkMode?"Koyu":"Açık"} Mod</span>
          <button onClick={()=>setDarkMode(d=>!d)} style={{width:44,height:24,borderRadius:12,border:"none",cursor:"pointer",position:"relative",background:darkMode?"#3b82f6":"#d1d5db",transition:"background .2s",padding:0}}>
            <span style={{position:"absolute",top:3,left:darkMode?22:3,width:18,height:18,borderRadius:"50%",background:"#fff",transition:"left .2s",boxShadow:"0 1px 3px rgba(0,0,0,.3)",display:"block"}}/>
          </button>
        </div>
      </div>

      <div style={{display:"flex",flex:1,overflow:"hidden"}}>
        {/* Sidebar */}
        <div style={{width:110,background:"#1565A0",display:"flex",flexDirection:"column",alignItems:"center",padding:"8px 0",gap:2,flexShrink:0}}>
          {[
            ["hatali",<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>,"Ana Ekran"],
            ["personel",<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>,"Personel"],
            ["giris",<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg>,"Giriş / Çıkış"],
            ["puantaj",<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="8" y1="14" x2="8" y2="14"/><line x1="12" y1="14" x2="12" y2="14"/><line x1="16" y1="14" x2="16" y2="14"/></svg>,"Aylık Puantaj"],
            ["shift",<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>,"Shift Atama"],
          ].filter(([id])=>modulGorebilirMi(kullanici, id)).map(([id,icon,label])=>(
            <button key={id} onClick={()=>{setActiveMenu(id);setActiveSubMenu(null);setOpenDropdown(null);}} style={{width:"92%",padding:"12px 4px",background:activeMenu===id?"rgba(255,255,255,0.2)":"none",border:"none",borderLeft:activeMenu===id?"3px solid rgba(255,255,255,0.8)":"3px solid transparent",color:"#fff",cursor:"pointer",display:"flex",flexDirection:"column",alignItems:"center",gap:5,fontFamily:"var(--font-sans)",opacity:activeMenu===id?1:0.7,transition:"all .15s",outline:"none",borderRadius:"0 6px 6px 0"}}>
              {icon}
              <span style={{fontSize:10,textAlign:"center",lineHeight:1.3,fontWeight:activeMenu===id?600:400}}>{label}</span>
            </button>
          ))}
          <div style={{flex:1}} />
          {/* Kullanıcı bilgisi */}
          <div style={{padding:"8px 6px",marginBottom:4,textAlign:"center"}}>
            <div style={{width:32,height:32,borderRadius:"50%",background:"rgba(255,255,255,0.2)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:700,color:"#fff",margin:"0 auto 4px"}}>{kullanici.ad.charAt(0)}</div>
            <div style={{fontSize:9,color:"rgba(255,255,255,0.6)",lineHeight:1.3}}>{kullanici.ad}</div>
            <div style={{fontSize:8,color:"rgba(255,255,255,0.4)"}}>{yetkiLabel[kullanici.yetki]||kullanici.yetki}</div>
          </div>
          <button onClick={handleLogout} style={{width:"92%",padding:"10px 4px",background:"none",border:"none",borderLeft:"3px solid transparent",color:"rgba(255,255,255,0.5)",cursor:"pointer",display:"flex",flexDirection:"column",alignItems:"center",gap:4,fontFamily:"var(--font-sans)"}} title="Çıkış Yap">
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
            <span style={{fontSize:9}}>Çıkış</span>
          </button>
        </div>

        {/* Main content */}
        <div style={{flex:1,overflow:"auto",display:"flex",flexDirection:"column",background:"var(--page-bg)"}}>
          <div style={{padding:"12px 20px",borderBottom:`1px solid var(--grid-line)`,background:"var(--card-bg)",display:"flex",justifyContent:"space-between",alignItems:"center",flexShrink:0}}>
            <div>
              <div style={{fontSize:15,fontWeight:500,color:"var(--text-primary)"}}>{pageTitle}</div>
              <div style={{fontSize:12,color:"var(--text-secondary)",marginTop:2,fontWeight:500}}>{BUGUN_LABEL}</div>
            </div>
            <div style={{display:"flex",gap:8,alignItems:"center"}}>
              <span id="puantaj-bilgi" style={{fontSize:12,color:"var(--text-tertiary)"}}></span>
              {activeMenu==="personel" && !readOnly && <Btn primary onClick={()=>{setSelectedPersonel({...emptyP});setShowAddModal(true);}}>+ Yeni Ekle</Btn>}
              {activeMenu==="personel" && kullanici.yetki==="admin" && (
                <button onClick={()=>setShowExcelImport(true)} style={{display:"flex",flexDirection:"column",alignItems:"center",gap:3,padding:"6px 10px",background:"var(--input-bg)",border:"1px solid var(--input-border)",borderRadius:6,cursor:"pointer",color:"var(--text-primary)",fontFamily:"var(--font-sans)",minWidth:58}}
                  onMouseEnter={e=>e.currentTarget.style.background="var(--tr-hover)"}
                  onMouseLeave={e=>e.currentTarget.style.background="var(--input-bg)"}>
                  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
                  <span style={{fontSize:10,whiteSpace:"nowrap",fontWeight:500}}>Excel'den Aktar</span>
                </button>
              )}
              {activeMenu==="shift" && <span style={{fontSize:12,color:"rgba(255,255,255,0.6)"}}>Shift Atama</span>}
            </div>
          </div>

          <div style={{flex:1,overflow:"auto",padding:20,background:"var(--page-bg)"}}>

            {/* ANA EKRAN */}
            {activeMenu==="hatali" && (
              <div style={{display:"flex",gap:16}}>
                <div style={{flex:1}}>
                  <HataliHareketler personeller={personeller} kullanici={kullanici} aciklamaGizle={aciklamaGizle} setAciklamaGizle={setAciklamaGizle} hiddenColsExt={hataliHiddenCols} setHiddenColsExt={setHataliHiddenCols} uid={uid} />
                </div>
                <div style={{width:280,flexShrink:0,display:"flex",flexDirection:"column",gap:12}}>
                  {/* Yaklaşan Doğum Günleri */}
                  {(() => {
                    const bugun = new Date(); bugun.setHours(0,0,0,0);
                    const gorPersList = personeller.filter(p => gorebilirMi(kullanici, p.departman) && p.dogumTarihi);
                    const yaklasanlar = gorPersList.filter(p => {
                      const [g,m] = p.dogumTarihi.split(".");
                      if(!g||!m) return false;
                      const yilBu = bugun.getFullYear();
                      let dg = new Date(yilBu, parseInt(m)-1, parseInt(g)); dg.setHours(0,0,0,0);
                      if(dg < bugun) dg = new Date(yilBu+1, parseInt(m)-1, parseInt(g));
                      const fark = Math.round((dg-bugun)/(1000*60*60*24));
                      return fark >= 0 && fark <= 7;
                    }).map(p => {
                      const [g,m] = p.dogumTarihi.split(".");
                      const yilBu = bugun.getFullYear();
                      let dg = new Date(yilBu, parseInt(m)-1, parseInt(g)); dg.setHours(0,0,0,0);
                      if(dg < bugun) dg = new Date(yilBu+1, parseInt(m)-1, parseInt(g));
                      const fark = Math.round((dg-bugun)/(1000*60*60*24));
                      return {...p, fark, dgStr:`${g}.${m}`};
                    }).sort((a,b)=>a.fark-b.fark);
                    return (
                      <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8}}>
                        <div style={{padding:"8px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:12,fontWeight:500,display:"flex",justifyContent:"space-between"}}>
                          <span>🎂 Yaklaşan Doğum Günleri</span>
                          {yaklasanlar.length>0 && <span style={{background:"#FAEEDA",color:"#854F0B",borderRadius:20,padding:"1px 8px",fontSize:11,fontWeight:700}}>{yaklasanlar.length}</span>}
                        </div>
                        {yaklasanlar.length===0
                          ? <div style={{padding:12,fontSize:11,color:"var(--text-tertiary)",textAlign:"center"}}>7 gün içinde doğum günü yok</div>
                          : yaklasanlar.map(p=>(
                            <div key={p.id} style={{display:"flex",gap:8,padding:"7px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:11,alignItems:"center"}}>
                              <span style={{flex:1,fontWeight:600}}>{p.ad} {p.soyad}</span>
                              <span style={{color:"var(--text-tertiary)",fontSize:10}}>{p.dgStr}</span>
                              <span style={{background:p.fark===0?"#FAEEDA":"#F1EFE8",color:p.fark===0?"#854F0B":"#5F5E5A",padding:"1px 7px",borderRadius:10,fontSize:10,fontWeight:600}}>
                                {p.fark===0?"Bugün":`${p.fark} gün`}
                              </span>
                            </div>
                          ))
                        }
                      </div>
                    );
                  })()}

                  {/* 2 Aylık Deneme Süresi */}
                  {(() => {
                    const bugun = new Date(); bugun.setHours(0,0,0,0);
                    const gorPersList = personeller.filter(p => gorebilirMi(kullanici, p.departman) && p.isGiris);
                    const yaklasanlar = gorPersList.map(p => {
                      const [g,m,y] = p.isGiris.split(".");
                      if(!g||!m||!y) return null;
                      const giris = new Date(parseInt(y),parseInt(m)-1,parseInt(g)); giris.setHours(0,0,0,0);
                      const hedef = new Date(giris); hedef.setDate(hedef.getDate()+60);
                      const kalanGun = Math.round((hedef-bugun)/(1000*60*60*24));
                      return kalanGun>=0&&kalanGun<=7 ? {...p, kalanGun, hedefStr:`${String(hedef.getDate()).padStart(2,"0")}.${String(hedef.getMonth()+1).padStart(2,"0")}.${hedef.getFullYear()}`} : null;
                    }).filter(Boolean).sort((a,b)=>a.kalanGun-b.kalanGun);
                    return (
                      <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8}}>
                        <div style={{padding:"8px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:12,fontWeight:500,display:"flex",justifyContent:"space-between"}}>
                          <span>⏱ 2 Aylık Deneme Süresi</span>
                          {yaklasanlar.length>0 && <span style={{background:"#FCEBEB",color:"#A32D2D",borderRadius:20,padding:"1px 8px",fontSize:11,fontWeight:700}}>{yaklasanlar.length}</span>}
                        </div>
                        {yaklasanlar.length===0
                          ? <div style={{padding:12,fontSize:11,color:"var(--text-tertiary)",textAlign:"center"}}>7 gün içinde biten deneme yok</div>
                          : yaklasanlar.map(p=>(
                            <div key={p.id} style={{display:"flex",gap:8,padding:"7px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:11,alignItems:"center"}}>
                              <div style={{flex:1}}>
                                <div style={{fontWeight:600}}>{p.ad} {p.soyad}</div>
                                <div style={{fontSize:10,color:"var(--text-tertiary)"}}>{p.departman}</div>
                              </div>
                              <div style={{textAlign:"right"}}>
                                <div style={{background:p.kalanGun<=3?"#FCEBEB":"#FAEEDA",color:p.kalanGun<=3?"#A32D2D":"#854F0B",padding:"1px 7px",borderRadius:10,fontSize:10,fontWeight:700}}>
                                  {p.kalanGun===0?"Bugün bitiyor":`${p.kalanGun} gün`}
                                </div>
                                <div style={{fontSize:9,color:"var(--text-tertiary)",marginTop:1}}>{p.hedefStr}</div>
                              </div>
                            </div>
                          ))
                        }
                      </div>
                    );
                  })()}

                  {/* 6 Aylık Süre */}
                  {(() => {
                    const bugun = new Date(); bugun.setHours(0,0,0,0);
                    const gorPersList = personeller.filter(p => gorebilirMi(kullanici, p.departman) && p.isGiris);
                    const yaklasanlar = gorPersList.map(p => {
                      const [g,m,y] = p.isGiris.split(".");
                      if(!g||!m||!y) return null;
                      const giris = new Date(parseInt(y),parseInt(m)-1,parseInt(g)); giris.setHours(0,0,0,0);
                      const hedef = new Date(giris); hedef.setDate(hedef.getDate()+180);
                      const kalanGun = Math.round((hedef-bugun)/(1000*60*60*24));
                      return kalanGun>=0&&kalanGun<=7 ? {...p, kalanGun, hedefStr:`${String(hedef.getDate()).padStart(2,"0")}.${String(hedef.getMonth()+1).padStart(2,"0")}.${hedef.getFullYear()}`} : null;
                    }).filter(Boolean).sort((a,b)=>a.kalanGun-b.kalanGun);
                    return (
                      <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8}}>
                        <div style={{padding:"8px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:12,fontWeight:500,display:"flex",justifyContent:"space-between"}}>
                          <span>📅 6 Aylık Süre Bitiyor</span>
                          {yaklasanlar.length>0 && <span style={{background:"#FCEBEB",color:"#A32D2D",borderRadius:20,padding:"1px 8px",fontSize:11,fontWeight:700}}>{yaklasanlar.length}</span>}
                        </div>
                        {yaklasanlar.length===0
                          ? <div style={{padding:12,fontSize:11,color:"var(--text-tertiary)",textAlign:"center"}}>7 gün içinde biten 6 ay yok</div>
                          : yaklasanlar.map(p=>(
                            <div key={p.id} style={{display:"flex",gap:8,padding:"7px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:11,alignItems:"center"}}>
                              <div style={{flex:1}}>
                                <div style={{fontWeight:600}}>{p.ad} {p.soyad}</div>
                                <div style={{fontSize:10,color:"var(--text-tertiary)"}}>{p.departman}</div>
                              </div>
                              <div style={{textAlign:"right"}}>
                                <div style={{background:p.kalanGun<=3?"#FCEBEB":"#FAEEDA",color:p.kalanGun<=3?"#A32D2D":"#854F0B",padding:"1px 7px",borderRadius:10,fontSize:10,fontWeight:700}}>
                                  {p.kalanGun===0?"Bugün bitiyor":`${p.kalanGun} gün`}
                                </div>
                                <div style={{fontSize:9,color:"var(--text-tertiary)",marginTop:1}}>{p.hedefStr}</div>
                              </div>
                            </div>
                          ))
                        }
                      </div>
                    );
                  })()}
                  {/* Onay bekleyen */}
                  <div style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8}}>
                    <div style={{padding:"8px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:12,fontWeight:500,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                      <span>Onay Bekleyen Shift/İzin Atamaları</span>
                      {(() => {
                        const bekleyenler = getOnayBekleyen().filter(o=>o.durum==="bekliyor" && (kullanici.yetki==="admin" || o.pid===String(kullanici.id)));
                        return bekleyenler.length>0 && <span style={{background:"#FAEEDA",color:"#854F0B",borderRadius:20,padding:"1px 8px",fontSize:11,fontWeight:700}}>{bekleyenler.length}</span>;
                      })()}
                    </div>
                    {(() => {
                      void onayTick; // onayTick değişince yeniden render et
                      const tumBekleyenler = getOnayBekleyen();
                      // Admin: hepsini görür. Kullanıcı: sadece kendi girdiklerini
                      const bekleyenler = tumBekleyenler.filter(o => {
                        if(o.durum !== "bekliyor") return false;
                        if(kullanici.yetki === "admin") return true;
                        return String(o.pid) === String(kullanici.id);
                      });
                      if(bekleyenler.length===0) return <div style={{padding:12,fontSize:11,color:"var(--text-tertiary)",textAlign:"center"}}>Bekleyen atama yok</div>;
                      return (
                        <div style={{maxHeight:300,overflowY:"auto"}}>
                          {bekleyenler.slice(0,20).map((o)=>{
                            const sObj = [...(SHIFTS||[]),...(IZINLER||[])].find(s=>s.kod===o.kod);
                            const isIzin = o.tip === "izin";
                            return (
                              <div key={o.id} style={{display:"flex",gap:10,padding:"8px 12px",borderBottom:"0.5px solid var(--grid-line)",fontSize:12,alignItems:"center"}}>
                                <span style={{fontSize:13}}>{isIzin?"📋":"⏳"}</span>
                                <span style={{fontWeight:600,flex:1}}>{o.personelAd}</span>
                                <span style={{background:sObj?.bg||"#F1EFE8",color:sObj?.renk||"#5F5E5A",padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:700,whiteSpace:"nowrap"}}>{sObj?.ad||o.kod}</span>
                                <span style={{color:"var(--text-tertiary)",fontSize:11,whiteSpace:"nowrap"}}>{o.iso}</span>
                                {kullanici.yetki==="admin" ? (
                                  <div style={{display:"flex",gap:4,flexShrink:0}}>
                                    <button onClick={()=>{
                                      const sd = getShiftData();
                                      sd[`${o.pid}-${o.iso}`] = o.kod;
                                      saveShiftData(sd);
                                      const yeni = getOnayBekleyen().map(x=>x.id===o.id?{...x,durum:"onaylandi"}:x);
                                      saveOnayBekleyen(yeni);
                                      setOnayTick(t=>t+1);
                                    }} style={{background:"#EAF3DE",color:"#3B6D11",border:"none",borderRadius:4,padding:"2px 10px",cursor:"pointer",fontSize:11,fontWeight:700}}>✓ Onayla</button>
                                    <button onClick={()=>{
                                      if(!confirm(`${o.personelAd} — ${o.iso} talebi reddedilsin mi?`)) return;
                                      const yeni = getOnayBekleyen().map(x=>x.id===o.id?{...x,durum:"reddedildi"}:x);
                                      saveOnayBekleyen(yeni);
                                      setOnayTick(t=>t+1);
                                    }} style={{background:"#FCEBEB",color:"#A32D2D",border:"none",borderRadius:4,padding:"2px 8px",cursor:"pointer",fontSize:11,fontWeight:700}}>✕</button>
                                  </div>
                                ) : (
                                  <span style={{background:"#FAEEDA",color:"#854F0B",padding:"2px 8px",borderRadius:4,fontSize:10,fontWeight:600,flexShrink:0}}>Onay Bekleniyor</span>
                                )}
                              </div>
                            );
                          })}
                        </div>
                      );
                    })()}
                  </div>
                </div>
              </div>
            )}

            {/* PERSONEL LİSTESİ */}
            {activeMenu==="personel" && (
              <PersonelListesi
                personeller={personeller}
                filteredPersonel={filteredPersonel}
                searchText={searchText} setSearchText={setSearchText}
                deptFilter={deptFilter} setDeptFilter={setDeptFilter}
                durumFilter={durumFilter} setDurumFilter={setDurumFilter}
                onKartAc={setSelectedPersonel}
                onYeniEkle={()=>{setSelectedPersonel({...emptyP});setShowAddModal(true);}}
                onKapat={()=>setActiveMenu("hatali")}
                uid={uid}
                readOnly={readOnly}
                aktifKullanici={kullanici}
                alanIzinleri={alanIzinleri}
              />
            )}

            {activeMenu==="giris" && <PersonelHareketleri personeller={personeller} uid={uid} />}
            {activeMenu==="puantaj" && <AylikPuantaj personeller={personeller} kullanici={kullanici} />}
            {activeMenu==="shift" && <ShiftAtama personeller={personeller} kullanici={kullanici} />}
            {activeMenu==="tanimlar" && <Tanimlar subMenu={activeSubMenu} aktifKullanici={kullanici} alanIzinleri={alanIzinleri} setAlanIzni={setAlanIzni} personeller={personeller} onPersonelGuncelle={setPersoneller} />}
            {activeMenu==="raporlar" && <Raporlar subMenu={activeSubMenu} />}
            {activeMenu==="bakim" && (
              <div style={{padding:20,color:"var(--text-secondary)",fontSize:13}}>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
                  {bakimMenu.map(item=>(
                    <div key={item} onClick={()=>{if(item==="Toplu İzin Girişi") setShowTopluIzin(true);}}
                      style={{background:"var(--card-bg)",border:"0.5px solid var(--grid-line)",borderRadius:8,padding:"14px 16px",cursor:"pointer",display:"flex",alignItems:"center",gap:10}}
                      onMouseEnter={e=>e.currentTarget.style.background="var(--input-bg)"}
                      onMouseLeave={e=>e.currentTarget.style.background="var(--card-bg)"}>
                      <span style={{fontSize:20}}>{item==="Toplu İzin Girişi"?"📋":"⚙️"}</span>
                      <span style={{fontSize:13,fontWeight:500,color:"var(--text-primary)"}}>{item}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Modals */}
      {(selectedPersonel && !showAddModal) && <PersonelKartiSafe p={selectedPersonel} onClose={()=>setSelectedPersonel(null)} onSave={savePersonel} aktifKullanici={kullanici} />}
      {showAddModal && selectedPersonel && <PersonelKartiSafe p={selectedPersonel} onClose={()=>{setShowAddModal(false);setSelectedPersonel(null);}} onSave={savePersonel} aktifKullanici={kullanici} />}
      {showExcelImport && <ExcelImport personeller={personeller} onClose={()=>setShowExcelImport(false)} onSave={(yeni)=>{setPersoneller(yeni);}} />}

      {/* Toplu İzin Girişi Modalı */}
      {showTopluIzin && (() => {
        const TopluIzin = () => {
          const [basTarih, setBasTarih] = React.useState(BUGUN_ISO);
          const [bitTarih, setBitTarih] = React.useState(BUGUN_ISO);
          const [dept, setDept] = React.useState("");
          const [pid, setPid] = React.useState("");
          const [izinKod, setIzinKod] = React.useState(IZINLER[0]?.kod||"YI");
          const [sonuc, setSonuc] = React.useState(null);

          const deptPersonel = dept ? personeller.filter(p=>p.departman===dept && p.durum!=="Ayrıldı") : [];

          const uygula = () => {
            if(!basTarih||!bitTarih) { alert("Tarih aralığı seçin."); return; }
            if(!pid) { alert("Personel seçin."); return; }
            const per = personeller.find(p=>String(p.id)===String(pid));
            if(!per) return;
            // Başlangıç ve bitiş arasındaki tüm günleri bul
            const gunler = [];
            let cur = new Date(basTarih);
            const bit = new Date(bitTarih);
            while(cur <= bit) {
              gunler.push(cur.toISOString().slice(0,10));
              cur.setDate(cur.getDate()+1);
            }
            // shift_data'ya yaz
            const sd = getShiftData();
            gunler.forEach(iso => { sd[`${per.id}-${iso}`] = izinKod; });
            saveShiftData(sd);
            setSonuc({ad:`${per.ad} ${per.soyad}`, gun:gunler.length, kod:izinKod});
          };

          return (
            <div style={{position:"fixed",top:0,left:0,width:"100%",height:"100%",background:"rgba(0,0,0,.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:400}}>
              <div style={{background:"var(--card-bg)",border:"1px solid var(--grid-line)",borderRadius:12,width:420}}>
                <div style={{padding:"14px 20px",borderBottom:"1px solid var(--grid-line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                  <span style={{fontWeight:600,fontSize:15}}>📋 Toplu İzin Giriş Formu</span>
                  <button onClick={()=>setShowTopluIzin(false)} style={{background:"none",border:"none",cursor:"pointer",fontSize:18,color:"var(--text-secondary)"}}>✕</button>
                </div>
                <div style={{padding:20,display:"flex",flexDirection:"column",gap:14}}>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
                    <FormRow label="Başlama Tarihi">
                      <input type="date" defaultValue={basTarih} onBlur={e=>{if(e.target.value?.length===10)setBasTarih(e.target.value);}} onChange={e=>{if(e.target.value?.length===10)setBasTarih(e.target.value);}}
                        style={{width:"100%",padding:"7px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:13,colorScheme:"dark"}} />
                    </FormRow>
                    <FormRow label="Bitiş Tarihi">
                      <input type="date" defaultValue={bitTarih} onBlur={e=>{if(e.target.value?.length===10)setBitTarih(e.target.value);}} onChange={e=>{if(e.target.value?.length===10)setBitTarih(e.target.value);}}
                        style={{width:"100%",padding:"7px 10px",border:"1px solid var(--input-border)",borderRadius:6,background:"var(--input-bg)",color:"var(--text-primary)",fontSize:13,colorScheme:"dark"}} />
                    </FormRow>
                  </div>
                  <FormRow label="Departman">
                    <Select value={dept} onChange={e=>{setDept(e.target.value);setPid("");}}>
                      <option value="">Lütfen Seçiniz</option>
                      {getDepartmanlar().map(d=><option key={d.ad} value={d.ad}>{d.ad}</option>)}
                    </Select>
                  </FormRow>
                  <FormRow label="Personel">
                    <Select value={pid} onChange={e=>setPid(e.target.value)}>
                      <option value="">Lütfen Seçiniz</option>
                      {deptPersonel.map(p=><option key={p.id} value={p.id}>{p.ad} {p.soyad}</option>)}
                    </Select>
                  </FormRow>
                  <FormRow label="Atanacak İzin">
                    <Select value={izinKod} onChange={e=>setIzinKod(e.target.value)}>
                      <optgroup label="─── Ücretli İzinler ───">
                        {IZINLER.filter(s=>s.tip!=="ucretsiz").map(s=><option key={s.kod} value={s.kod}>{s.ad}</option>)}
                      </optgroup>
                      <optgroup label="─── Ücretsiz İzinler ───">
                        {IZINLER.filter(s=>s.tip==="ucretsiz").map(s=><option key={s.kod} value={s.kod}>{s.ad}</option>)}
                      </optgroup>
                    </Select>
                  </FormRow>

                  {/* Özet */}
                  {basTarih && bitTarih && pid && (
                    <div style={{padding:"10px 14px",background:"var(--input-bg)",borderRadius:8,fontSize:12,color:"var(--text-secondary)"}}>
                      {(() => {
                        const gunSayisi = Math.round((new Date(bitTarih)-new Date(basTarih))/86400000)+1;
                        const per = personeller.find(p=>String(p.id)===String(pid));
                        const izin = IZINLER.find(s=>s.kod===izinKod);
                        return `${per?.ad||""} ${per?.soyad||""} — ${gunSayisi} gün — `;
                      })()}
                      <span style={{background:IZINLER.find(s=>s.kod===izinKod)?.bg,color:IZINLER.find(s=>s.kod===izinKod)?.renk,padding:"1px 8px",borderRadius:4,fontWeight:700,fontSize:12}}>{izinKod}</span>
                    </div>
                  )}

                  {sonuc && (
                    <div style={{padding:"10px 14px",background:"#EAF3DE",border:"1px solid #3B6D11",borderRadius:8,fontSize:13,color:"#3B6D11",fontWeight:500}}>
                      ✓ {sonuc.ad} için {sonuc.gun} gün <strong>{sonuc.kod}</strong> izni atandı.
                    </div>
                  )}
                </div>
                <div style={{padding:"12px 20px",borderTop:"1px solid var(--grid-line)",display:"flex",justifyContent:"flex-end",gap:8}}>
                  <Btn onClick={()=>setShowTopluIzin(false)}>Kapat</Btn>
                  <Btn primary onClick={uygula}>Kaydet</Btn>
                </div>
              </div>
            </div>
          );
        };
        return <TopluIzin />;
      })()}

      {/* Bottom status bar */}
      <div style={{background:"#1565A0",color:"rgba(255,255,255,0.8)",padding:"4px 16px",fontSize:11,display:"flex",gap:16,flexShrink:0}}>
        <span>Toplam Personel: {personeller.length}</span>
        <span>Çalışan: {personeller.filter(p=>p.durum==="Çalışıyor").length}</span>
        <span style={{marginLeft:"auto"}}>TimeCore · {BUGUN_TARIH}</span>
      </div>
    </div>
  );
}

// ─── ROOT WRAPPER ─────────────────────────────────────────────────────────────
// Kullanıcı giriş/çıkışında PDKSApp'i key ile yeniden mount eder
// → Her kullanıcı kendi localStorage key'inden sıfırdan başlar
export default function App() {
  const [kullanici, setKullanici] = useState(() => {
    try { const k = localStorage.getItem("pdks_aktif_kullanici"); return k ? JSON.parse(k) : null; }
    catch { return null; }
  });

  const handleLogin = (k) => {
    localStorage.setItem("pdks_aktif_kullanici", JSON.stringify(k));
    setKullanici(k);
  };
  const handleLogout = () => {
    setKullanici(null);
  };

  if(!kullanici) return (
    <>
      <GlobalStyle dark={true} />
      <LoginEkrani onLogin={handleLogin} />
    </>
  );

  // key={kullanici.id} → kullanıcı değişince PDKSApp tamamen yeniden mount edilir
  // Bu sayede her kullanıcı kendi localStorage'ından init olur
  return (
    <PDKSApp
      key={kullanici.id}
      kullanici={kullanici}
      onLogout={handleLogout}
    />
  );
}
