MediaWiki:Common.js: Difference between revisions

From Erakh Codex
Jump to navigation Jump to search
No edit summary
No edit summary
Line 130: Line 130:
     sp(dropdown, "box-sizing", "border-box");
     sp(dropdown, "box-sizing", "border-box");


    // 프로필 섹션
     var dpProfile = document.createElement("div");
     var dpProfile = document.createElement("div");
     sp(dpProfile, "padding", "1rem");
     sp(dpProfile, "padding", "1rem");
Line 163: Line 162:


     var dpTitle = document.createElement("div");
     var dpTitle = document.createElement("div");
     dpTitle.textContent = "Chronicler";
     dpTitle.textContent = "";
     sp(dpTitle, "font-family", "'Inter', sans-serif");
     sp(dpTitle, "font-family", "'Inter', sans-serif");
     sp(dpTitle, "font-size", "0.6875rem");
     sp(dpTitle, "font-size", "0.6875rem");
Line 173: Line 172:
     dpProfile.appendChild(dpTitle);
     dpProfile.appendChild(dpTitle);


    // 스탯 그리드
     var dpStats = document.createElement("div");
     var dpStats = document.createElement("div");
     sp(dpStats, "display", "grid");
     sp(dpStats, "display", "grid");
Line 185: Line 183:
       if (borderRight) sp(cell, "border-right", "1px solid #e2d9c8");
       if (borderRight) sp(cell, "border-right", "1px solid #e2d9c8");
       if (borderBottom) sp(cell, "border-bottom", "1px solid #e2d9c8");
       if (borderBottom) sp(cell, "border-bottom", "1px solid #e2d9c8");
       var valEl = document.createElement("div");
       var valEl = document.createElement("div");
       valEl.textContent = val;
       valEl.textContent = val;
Line 194: Line 191:
       sp(valEl, "color", "#2a2218");
       sp(valEl, "color", "#2a2218");
       sp(valEl, "margin-bottom", "2px");
       sp(valEl, "margin-bottom", "2px");
       var lblEl = document.createElement("div");
       var lblEl = document.createElement("div");
       lblEl.textContent = lbl;
       lblEl.textContent = lbl;
Line 202: Line 198:
       sp(lblEl, "color", "#9c8e80");
       sp(lblEl, "color", "#9c8e80");
       sp(lblEl, "text-transform", "uppercase");
       sp(lblEl, "text-transform", "uppercase");
       cell.appendChild(valEl);
       cell.appendChild(valEl);
       cell.appendChild(lblEl);
       cell.appendChild(lblEl);
Line 208: Line 203:
     }
     }


     var cellLevel = makeStatCell("—", "Level",      true,  true);
     var cellLevel = makeStatCell("—", "Level",      true,  true);
     var cellExp   = makeStatCell("—", "EXP",        false, true);
     var cellExp   = makeStatCell("—", "EXP",        false, true);
     var cellDays   = makeStatCell("—", "Days Active", true,  false);
     var cellDays = makeStatCell("—", "Days Active", true,  false);
     var cellEdits = makeStatCell("—", "Edits",      false, false);
     var cellEdits = makeStatCell("—", "Edits",      false, false);


     dpStats.appendChild(cellLevel);
     dpStats.appendChild(cellLevel);
Line 218: Line 213:
     dpStats.appendChild(cellEdits);
     dpStats.appendChild(cellEdits);


    // 메뉴 섹션
     var dpMenu = document.createElement("div");
     var dpMenu = document.createElement("div");
     sp(dpMenu, "padding", "0.25rem 0");
     sp(dpMenu, "padding", "0.25rem 0");
Line 268: Line 262:
       var isHidden = dropdown.style.display === "none";
       var isHidden = dropdown.style.display === "none";
       dropdown.style.display = isHidden ? "block" : "none";
       dropdown.style.display = isHidden ? "block" : "none";
       if (isHidden && !profileLoaded) {
       if (isHidden && !profileLoaded) {
         fetch("https://erakh.com/api/auth/me", { method: "GET", credentials: "include" })
         fetch("https://erakh.com/api/auth/me", { method: "GET", credentials: "include" })
Line 279: Line 272:
             cellDays.querySelector(".dp-stat-val").textContent  = data.login_days;
             cellDays.querySelector(".dp-stat-val").textContent  = data.login_days;
             cellEdits.querySelector(".dp-stat-val").textContent = data.edit_count;
             cellEdits.querySelector(".dp-stat-val").textContent = data.edit_count;
            dpTitle.textContent = data.title || "Chronicler";
           })
           })
           .catch(function() {});
           .catch(function() {});

Revision as of 23:51, 27 April 2026

(function () {
  var fontLink = document.createElement("link");
  fontLink.rel = "stylesheet";
  fontLink.href = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap";
  document.head.insertBefore(fontLink, document.head.firstChild);

  function getCookie(name) {
    var match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
    return match ? decodeURIComponent(match[1]) : null;
  }

  var user = null;
  try {
    var raw = getCookie("erakh_user");
    if (raw) user = JSON.parse(raw);
  } catch (e) {}

  if (user && user.exp) {
    var now = Math.floor(Date.now() / 1000);
    var remaining = user.exp - now;
    if (remaining < 5 * 60) {
      fetch("https://erakh.com/api/auth/refresh", { method: "POST", credentials: "include" })
        .catch(function() {});
    } else {
      var delay = (remaining - 5 * 60) * 1000;
      setTimeout(function() {
        fetch("https://erakh.com/api/auth/refresh", { method: "POST", credentials: "include" })
          .catch(function() {});
      }, delay);
    }
  }

  function sp(el, prop, val) {
    el.style.setProperty(prop, val, "important");
  }

  var header = document.createElement("header");
  sp(header, "position", "fixed");
  sp(header, "top", "0");
  sp(header, "left", "0");
  sp(header, "right", "0");
  sp(header, "z-index", "9999");
  sp(header, "width", "100%");
  sp(header, "background", "#f9f6f0");
  sp(header, "border-bottom", "1px solid #e2d9c8");
  sp(header, "display", "flex");
  sp(header, "align-items", "center");
  sp(header, "justify-content", "space-between");
  sp(header, "padding", "0 2rem");
  sp(header, "height", "56px");
  sp(header, "box-sizing", "border-box");

  var left = document.createElement("div");
  sp(left, "display", "flex");
  sp(left, "align-items", "center");
  sp(left, "gap", "1.75rem");

  var logo = document.createElement("a");
  logo.href = "https://erakh.com";
  logo.textContent = "Erakh Archive";
  sp(logo, "font-family", "'Inter', sans-serif");
  sp(logo, "font-size", "1.125rem");
  sp(logo, "font-weight", "500");
  sp(logo, "color", "#2a2218");
  sp(logo, "text-decoration", "none");
  sp(logo, "letter-spacing", "-0.01em");
  sp(logo, "text-transform", "none");
  sp(logo, "font-variant", "normal");
  sp(logo, "font-variant-caps", "normal");
  sp(logo, "line-height", "1");

  var nav = document.createElement("nav");
  sp(nav, "display", "flex");
  sp(nav, "align-items", "center");
  sp(nav, "gap", "1.5rem");

  var codexLink = document.createElement("a");
  codexLink.href = "https://codex.erakh.com";
  codexLink.textContent = "Codex";
  sp(codexLink, "font-family", "'Inter', sans-serif");
  sp(codexLink, "font-size", "1rem");
  sp(codexLink, "color", "#6b5e4e");
  sp(codexLink, "text-decoration", "none");
  sp(codexLink, "text-transform", "none");
  sp(codexLink, "font-variant", "normal");
  sp(codexLink, "line-height", "1");
  codexLink.addEventListener("mouseover", function() { this.style.setProperty("color", "#2a2218", "important"); });
  codexLink.addEventListener("mouseout",  function() { this.style.setProperty("color", "#6b5e4e", "important"); });

  nav.appendChild(codexLink);
  left.appendChild(logo);
  left.appendChild(nav);

  var right = document.createElement("div");
  sp(right, "display", "flex");
  sp(right, "align-items", "center");

  if (user && user.nickname) {
    var profile = document.createElement("div");
    sp(profile, "position", "relative");

    var avatar = document.createElement("div");
    avatar.textContent = user.nickname.slice(0, 1).toUpperCase();
    sp(avatar, "width", "32px");
    sp(avatar, "height", "32px");
    sp(avatar, "border-radius", "50%");
    sp(avatar, "background", "#e2d9c8");
    sp(avatar, "border", "1px solid #c8b99a");
    sp(avatar, "display", "flex");
    sp(avatar, "align-items", "center");
    sp(avatar, "justify-content", "center");
    sp(avatar, "cursor", "pointer");
    sp(avatar, "font-family", "'Inter', sans-serif");
    sp(avatar, "font-size", "0.75rem");
    sp(avatar, "font-weight", "500");
    sp(avatar, "color", "#2a2218");
    sp(avatar, "box-sizing", "border-box");

    var dropdown = document.createElement("div");
    sp(dropdown, "display", "none");
    sp(dropdown, "position", "absolute");
    sp(dropdown, "top", "calc(100% + 8px)");
    sp(dropdown, "right", "0");
    sp(dropdown, "background", "#f9f6f0");
    sp(dropdown, "border", "1px solid #e2d9c8");
    sp(dropdown, "min-width", "220px");
    sp(dropdown, "padding", "0");
    sp(dropdown, "box-shadow", "0 4px 16px rgba(0,0,0,0.06)");
    sp(dropdown, "z-index", "10000");
    sp(dropdown, "box-sizing", "border-box");

    var dpProfile = document.createElement("div");
    sp(dpProfile, "padding", "1rem");
    sp(dpProfile, "display", "flex");
    sp(dpProfile, "flex-direction", "column");
    sp(dpProfile, "align-items", "center");
    sp(dpProfile, "gap", "0.25rem");
    sp(dpProfile, "border-bottom", "1px solid #e2d9c8");

    var dpAvatar = document.createElement("div");
    dpAvatar.textContent = user.nickname.slice(0, 1).toUpperCase();
    sp(dpAvatar, "width", "44px");
    sp(dpAvatar, "height", "44px");
    sp(dpAvatar, "border-radius", "50%");
    sp(dpAvatar, "background", "#f0ebe0");
    sp(dpAvatar, "border", "1px solid #c8b99a");
    sp(dpAvatar, "display", "flex");
    sp(dpAvatar, "align-items", "center");
    sp(dpAvatar, "justify-content", "center");
    sp(dpAvatar, "font-family", "'Inter', sans-serif");
    sp(dpAvatar, "font-size", "1rem");
    sp(dpAvatar, "font-weight", "500");
    sp(dpAvatar, "color", "#c8a060");
    sp(dpAvatar, "margin-bottom", "0.25rem");

    var dpName = document.createElement("div");
    dpName.textContent = user.nickname;
    sp(dpName, "font-family", "'Inter', sans-serif");
    sp(dpName, "font-size", "0.875rem");
    sp(dpName, "font-weight", "500");
    sp(dpName, "color", "#2a2218");

    var dpTitle = document.createElement("div");
    dpTitle.textContent = "—";
    sp(dpTitle, "font-family", "'Inter', sans-serif");
    sp(dpTitle, "font-size", "0.6875rem");
    sp(dpTitle, "color", "#9c8e80");
    sp(dpTitle, "font-style", "italic");

    dpProfile.appendChild(dpAvatar);
    dpProfile.appendChild(dpName);
    dpProfile.appendChild(dpTitle);

    var dpStats = document.createElement("div");
    sp(dpStats, "display", "grid");
    sp(dpStats, "grid-template-columns", "1fr 1fr");
    sp(dpStats, "border-bottom", "1px solid #e2d9c8");

    function makeStatCell(val, lbl, borderRight, borderBottom) {
      var cell = document.createElement("div");
      sp(cell, "padding", "0.5rem 0");
      sp(cell, "text-align", "center");
      if (borderRight) sp(cell, "border-right", "1px solid #e2d9c8");
      if (borderBottom) sp(cell, "border-bottom", "1px solid #e2d9c8");
      var valEl = document.createElement("div");
      valEl.textContent = val;
      valEl.className = "dp-stat-val";
      sp(valEl, "font-family", "'Inter', sans-serif");
      sp(valEl, "font-size", "0.8125rem");
      sp(valEl, "font-weight", "500");
      sp(valEl, "color", "#2a2218");
      sp(valEl, "margin-bottom", "2px");
      var lblEl = document.createElement("div");
      lblEl.textContent = lbl;
      sp(lblEl, "font-family", "'Inter', sans-serif");
      sp(lblEl, "font-size", "0.5625rem");
      sp(lblEl, "letter-spacing", "0.1em");
      sp(lblEl, "color", "#9c8e80");
      sp(lblEl, "text-transform", "uppercase");
      cell.appendChild(valEl);
      cell.appendChild(lblEl);
      return cell;
    }

    var cellLevel = makeStatCell("—", "Level",       true,  true);
    var cellExp   = makeStatCell("—", "EXP",         false, true);
    var cellDays  = makeStatCell("—", "Days Active", true,  false);
    var cellEdits = makeStatCell("—", "Edits",       false, false);

    dpStats.appendChild(cellLevel);
    dpStats.appendChild(cellExp);
    dpStats.appendChild(cellDays);
    dpStats.appendChild(cellEdits);

    var dpMenu = document.createElement("div");
    sp(dpMenu, "padding", "0.25rem 0");

    var profileLink = document.createElement("a");
    profileLink.href = "https://erakh.com/profile";
    profileLink.textContent = "Profile";
    sp(profileLink, "display", "block");
    sp(profileLink, "width", "100%");
    sp(profileLink, "padding", "0.5rem 1rem");
    sp(profileLink, "font-family", "'Inter', sans-serif");
    sp(profileLink, "font-size", "0.8125rem");
    sp(profileLink, "color", "#2a2218");
    sp(profileLink, "text-decoration", "none");
    sp(profileLink, "box-sizing", "border-box");
    profileLink.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
    profileLink.addEventListener("mouseout",  function() { this.style.setProperty("background", "transparent", "important"); });

    var signOutBtn = document.createElement("button");
    signOutBtn.textContent = "Sign out";
    sp(signOutBtn, "display", "block");
    sp(signOutBtn, "width", "100%");
    sp(signOutBtn, "padding", "0.5rem 1rem");
    sp(signOutBtn, "font-family", "'Inter', sans-serif");
    sp(signOutBtn, "font-size", "0.8125rem");
    sp(signOutBtn, "color", "#a04040");
    sp(signOutBtn, "text-align", "left");
    sp(signOutBtn, "background", "transparent");
    sp(signOutBtn, "border", "none");
    sp(signOutBtn, "cursor", "pointer");
    sp(signOutBtn, "box-sizing", "border-box");
    signOutBtn.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
    signOutBtn.addEventListener("mouseout",  function() { this.style.setProperty("background", "transparent", "important"); });
    signOutBtn.addEventListener("click", function () {
      fetch("https://erakh.com/api/auth/logout", { method: "POST", credentials: "include" })
        .then(function () { window.location.href = "https://erakh.com"; });
    });

    dpMenu.appendChild(profileLink);
    dpMenu.appendChild(signOutBtn);

    dropdown.appendChild(dpProfile);
    dropdown.appendChild(dpStats);
    dropdown.appendChild(dpMenu);

    var profileLoaded = false;

    avatar.addEventListener("click", function () {
      var isHidden = dropdown.style.display === "none";
      dropdown.style.display = isHidden ? "block" : "none";
      if (isHidden && !profileLoaded) {
        fetch("https://erakh.com/api/auth/me", { method: "GET", credentials: "include" })
          .then(function(r) { return r.json(); })
          .then(function(data) {
            if (data.isNew) return;
            profileLoaded = true;
            cellLevel.querySelector(".dp-stat-val").textContent = "Lv. " + data.level;
            cellExp.querySelector(".dp-stat-val").textContent   = data.exp_in_level + " / " + data.exp_to_next;
            cellDays.querySelector(".dp-stat-val").textContent  = data.login_days;
            cellEdits.querySelector(".dp-stat-val").textContent = data.edit_count;
            dpTitle.textContent = data.title || "Chronicler";
          })
          .catch(function() {});
      }
    });

    document.addEventListener("click", function (e) {
      var inside = profile.contains(e.target);
      if (inside === false) {
        dropdown.style.display = "none";
      }
    });

    profile.appendChild(avatar);
    profile.appendChild(dropdown);
    right.appendChild(profile);

  } else {
    var loginBtn = document.createElement("a");
    loginBtn.href = "https://erakh.com/login?redirect=" + encodeURIComponent(window.location.href);
    loginBtn.textContent = "Sign in";
    sp(loginBtn, "font-family", "'Inter', sans-serif");
    sp(loginBtn, "font-size", "0.8125rem");
    sp(loginBtn, "font-weight", "500");
    sp(loginBtn, "color", "#2a2218");
    sp(loginBtn, "text-decoration", "none");
    sp(loginBtn, "padding", "0.4rem 1rem");
    sp(loginBtn, "border", "1px solid #c8b99a");
    sp(loginBtn, "background", "transparent");
    sp(loginBtn, "cursor", "pointer");
    sp(loginBtn, "box-sizing", "border-box");
    sp(loginBtn, "line-height", "1");
    loginBtn.addEventListener("mouseover", function() {
      this.style.setProperty("border-color", "#c8a060", "important");
      this.style.setProperty("background", "#f0ebe0", "important");
    });
    loginBtn.addEventListener("mouseout", function() {
      this.style.setProperty("border-color", "#c8b99a", "important");
      this.style.setProperty("background", "transparent", "important");
    });
    right.appendChild(loginBtn);
  }

  header.appendChild(left);
  header.appendChild(right);
  document.body.insertBefore(header, document.body.firstChild);
})();