/* eslint-disable */
// ─────────────────────────────────────────────────────────────
// searchgg · 메인 홈 (레트로 구조형 · 올리브 포인트 · 각진 패널 레이아웃)
// 공지/업데이트/이벤트 전면 · 이벤트 카드 이미지 슬롯
// window.Home
// ─────────────────────────────────────────────────────────────
const { useState: useStateH } = React;
const PT = '#48515f'; // 올리브/카키 포인트
const PT_SOFT = 'rgba(72,81,95,.12)';
const HEAD = '#f1f3f5'; // 패널 헤더바 배경
const CH = "'Chakra Petch',sans-serif";
const panel = { border: '1px solid var(--line2)', background: '#fff', borderRadius: 5 };
// 패널 (채워진 헤더바 + 보더)
function Panel({ title, en, right, children, bodyPad = '8px 14px 12px' }) {
return (
{title}
{en && {en}}
{right}
{children}
);
}
// 세그먼트 탭 (각진)
function Seg({ tabs, value, onChange }) {
return (
{tabs.map((t, i) => {
const on = value === t;
return (
);
})}
);
}
// ── 상단 유틸 바 ──
function TopBar() {
return (
{['로그인', '회원가입', '쿠폰등록', '고객센터'].map((t, i) => (
{i > 0 && }
{t}
))}
);
}
// ── 메인 네비(GNB) ──
function Nav({ onLogin, onClan, onCommunity, active = '홈' }) {
const items = ['홈', '전적검색', '커뮤니티', '클랜'];
return (
);
}
// ── 검색 히어로(구조형 밴드) ──
function Hero({ onPick }) {
const SA = window.SA, me = SA.me;
return (
SUDDEN ATTACK RECORD SEARCH
전적 검색
어서와요, {me.name} 님
);
}
// ── 섹션 헤더(채워진 바) ──
function BarHead({ title, en, more }) {
return (
{title}
{en && {en}}
{more &&
전체보기 +}
);
}
// ── 진행중인 이벤트 (캐러셀) ──
function EventStrip() {
const SA = window.SA;
const PER = 4;
const pages = Math.ceil(SA.events.length / PER);
const [page, setPage] = useStateH(0);
const [hover, setHover] = useStateH(false);
React.useEffect(() => {
if (hover || pages <= 1) return;
const t = setInterval(() => setPage((p) => (p + 1) % pages), 5000);
return () => clearInterval(t);
}, [hover, pages]);
const go = (d) => setPage((p) => (p + d + pages) % pages);
const arrow = (dir) => (
);
return (
setHover(true)} onMouseLeave={() => setHover(false)}>
진행중인 이벤트
ON-GOING EVENT
{page + 1} / {pages}
{arrow('L')}{arrow('R')}
{Array.from({ length: pages }).map((_, pi) => (
{SA.events.slice(pi * PER, pi * PER + PER).map((e, i) => {
const gi = pi * PER + i;
const urgent = e.dday.startsWith('D-') && +e.dday.slice(2) <= 3;
return (
{e.tag}
{e.dday}
{e.title}
{e.sub}
{e.period}
);
})}
))}
{Array.from({ length: pages }).map((_, i) => (
);
}
const rowDiv = (i, n) => ({ borderBottom: i < n - 1 ? '1px solid #eaecef' : 'none' });
// ── 지금 방송 중 LIVE (치지직 / 숲 / 유튜브) ──
function StreamLive({ onPick }) {
const SA = window.SA;
const [tab, setTab] = useStateH('전체');
const list = tab === '전체' ? SA.streams : SA.streams.filter((s) => s.platform === tab);
const totalView = SA.streams.reduce((a, s) => a + s.viewers, 0);
return (
}>
LIVE
{list.length}개 방송
·
시청자 {SA.fmt(totalView)}명
{list.map((s, i) => {
const pf = SA.streamPlatforms[s.platform];
const player = SA.allPlayers.find((p) => p.name === s.streamer);
return (
);
})}
);
}
// ── SA 소식 ──
function SANews() {
const SA = window.SA;
const [tab, setTab] = useStateH('공지사항');
const rows = SA.news[tab];
return (
} bodyPad="2px 14px 6px">
{rows.map((r, i) => (
{r.date}
{r.title}
))}
);
}
// ── 커뮤니티 ──
function Community({ onAll }) {
const SA = window.SA;
const rows = [...SA.community['자유'], ...SA.community['공략']]
.sort((a, b) => (b.hot ? 1 : 0) - (a.hot ? 1 : 0))
.slice(0, 6);
return (
전체 보기
} bodyPad="2px 14px 6px">
{rows.map((p, i) => (
{p.tag}
{p.title}
{p.hot && HOT}
{p.cmt}
{p.time}
))}
);
}
// ── 내 전적 요약 ──
function MeCard({ onPick }) {
const SA = window.SA, me = SA.me;
const [scope, setScope] = useStateH('통합');
const rankNo = scope === '통합' ? me.rankNoTotal : me.rankNoSeason;
const selRank = scope === '통합' ? me.rankTotal : me.rankSeason;
return (
}>
{me.name}
{me.clan}
{scope} 랭킹
{SA.fmt(rankNo)}위
{[['승·패', `${me.wins}/${me.losses}`], ['승률', me.wr + '%'], ['킬뎃', SA.kdPct(me.kda) + '%']].map(([k, v], i) => (
))}
);
}
// ── SA 랭킹 (5종 · 각 top10) ──
const SA_CATS = ['통합 계급', '시즌 계급', '랭크전', '공식 클랜', '클랜'];
function RankRow({ i, onClick, badge, name, tag, sub, value, unit }) {
return (
);
}
// ── 즐겨찾기 (페이지네이션) ──
function Favorites({ onPick }) {
const SA = window.SA;
const all = SA.favorites;
const PER = 5;
const pages = Math.ceil(all.length / PER);
const [page, setPage] = useStateH(0);
const start = page * PER;
const view = all.slice(start, start + PER);
return (
{all.length}명} bodyPad="0">
{view.map((f, i) => (
))}
{Array.from({ length: pages }).map((_, i) => (
))}
);
}
function pgBtn(disabled) {
return { width: 26, height: 26, borderRadius: 4, border: '1px solid var(--line2)', background: '#fff', color: disabled ? 'var(--line2)' : 'var(--t2)', cursor: disabled ? 'default' : 'pointer', fontFamily: "'Chakra Petch',sans-serif", fontWeight: 700, fontSize: 14 };
}
function SARanking({ onPick, onClan }) {
const SA = window.SA;
const [cat, setCat] = useStateH('통합 계급');
const [mode, setMode] = useStateH('솔로');
const tcol = Object.fromEntries(SA.tiers.map((t) => [t.name, t.color]));
const isClass = cat === '시즌 계급' || cat === '통합 계급';
const isRanked = cat === '랭크전';
const isRankedUser = isRanked && mode !== '클랜';
const isRankedClan = isRanked && mode === '클랜';
const isClan = cat === '공식 클랜' || cat === '클랜';
const classList = cat === '시즌 계급' ? SA.seasonClassRanking : SA.totalClassRanking;
const contentList = mode === '솔로' ? SA.soloRpRanking : SA.partyRpRanking;
const clanList = cat === '공식 클랜' ? SA.officialClanRanking : SA.generalClanRanking;
return (
TOP 10} bodyPad="11px 0 0">
{/* 카테고리 선택 */}
{SA_CATS.map((c) => {
const on = c === cat;
return (
);
})}
{/* 랭크전 하위 토글 */}
{isRanked && (
{['솔로', '파티', '클랜'].map((t, i) => {
const on = mode === t;
return (
);
})}
)}
{/* 계급 랭킹 */}
{isClass && classList.map((e, i) => {
const p = SA.allPlayers.find((x) => x.name === e.name);
return (
p && onPick(p)}
badge={p ? : null}
tag={p && p.clan} name={e.name} sub={p && p.rank.name}
value={SA.fmt(e.score)} unit="점" />
);
})}
{/* 랭크전(솔로/파티) 랭킹 */}
{isRankedUser && contentList.map((e, i) => {
const p = SA.allPlayers.find((x) => x.name === e.name);
const col = tcol[e.tier] || PT;
return (
p && onPick(p)}
badge={{e.tier[0]}
}
tag={p && p.clan} name={e.name} sub={{e.tier}}
value={SA.fmt(e.rp)} unit="RP" />
);
})}
{/* 랭크전(클랜) 랭킹 — 클랜 정보 */}
{isRankedClan && SA.clanRpRanking.map((c, i) => (
onClan && onClan(c.name)}
badge={{c.tag}
}
name={c.name} sub={`${c.members}명`} value={SA.fmt(c.rp)} unit="RP" />
))}
{/* 클랜 랭킹 */}
{isClan && clanList.map((c, i) => (
onClan && onClan(c.name)}
badge={{c.tag}
}
name={{c.name}{cat === '공식 클랜' && 인증}}
sub={`${c.members}명`} value={SA.fmt(c.rp)} unit="RP" />
))}
);
}
// ── 인기 검색 랭킹(가장 많이 조회된 유저) ──
function SearchRank({ onPick }) {
const SA = window.SA;
const trend = (m) => {
if (m === 'new') return NEW;
if (m === 0) return –;
const up = m > 0;
return {up ? '▲' : '▼'}{Math.abs(m)};
};
return (
최근 24시간} bodyPad="4px 0 0">
{SA.searchTrending.map((s, i) => {
const p = SA.allPlayers.find((x) => x.name === s.name);
return (
);
})}
);
}
// ── 시즌 현황 ──
function SeasonCard() {
const SA = window.SA, s = SA.season;
const [mapTab, setMapTab] = useStateH('5vs5');
const maps = mapTab === '5vs5' ? s.maps5v5 : s.maps3v3;
return (
{s.dday}} bodyPad="14px 14px">
시즌 진행{s.progress}%
시즌 맵
{['5vs5', '3vs3'].map((t, i) => {
const on = mapTab === t;
return (
);
})}
{maps.map((m) => {m})}
);
}
// ── 폼 좋은 유저 (연승 / 승률 / 킬뎃 탭) ──
function HotStreak({ onPick }) {
const SA = window.SA;
const [tab, setTab] = useStateH('연승');
let rows;
if (tab === '연승') {
rows = SA.hotStreak.map((e) => ({ p: SA.allPlayers.find((x) => x.name === e.name), streak: e.streak }));
} else if (tab === '승률') {
rows = [...SA.allPlayers].sort((a, b) => b.wr - a.wr).slice(0, 6).map((p) => ({ p }));
} else {
rows = [...SA.allPlayers].sort((a, b) => b.kda - a.kda).slice(0, 6).map((p) => ({ p }));
}
const metric = (p, streak) => {
if (tab === '연승') return (
{streak}연승
);
if (tab === '승률') return {p.wr}%;
return {SA.kdPct(p.kda)}%;
};
return (
} bodyPad="12px 14px 14px">
{rows.map(({ p, streak }, i) => p && (
))}
);
}
// ── 오늘의 전장 ──
function LiveStats() {
const SA = window.SA, L = SA.liveStats;
return (
{SA.fmt(L.totalMatches)}
매치
▲ {L.prevDelta}%
{L.matchModes.map(({ name, count }) => (
{name}
{SA.fmt(count)}
))}
오늘 제재
{L.bannedToday}명
);
}
function Footer() {
return (
searchgg는 서든어택 전적 조회를 위한 비공식 팬 사이트입니다. 본 페이지의 데이터는 데모용 예시입니다.
© 2026 searchgg
);
}
// ── 모집 중인 클랜 (포스터) ──
function RecruitPosters({ onPlaza, onOpenClan }) {
let pool = window.ClanRecruits ? window.ClanRecruits() : [];
try { if (localStorage.getItem('sa-my-recruit-active') === '0') pool = pool.filter((c) => c.name !== (window.SA.me.clan || '')); } catch (e) {}
const list = pool.slice().sort((a, b) => b.hot - a.hot).slice(0, 4);
if (!list.length) return null;
return (
전체 보기
} bodyPad="14px 14px">
{list.map((rc) => (
{rc.name}
랭킹 {rc.rank}위 · {rc.openings}명 모집
))}
);
}
function Home() {
const [sel, setSel] = useStateH(null);
const [login, setLogin] = useStateH(false);
const [clan, setClan] = useStateH(null);
const [plaza, setPlaza] = useStateH(false);
const [community, setCommunity] = useStateH(false);
return (
);
}
Object.assign(window, { Home, TopBar, Nav, Footer, Panel, Seg, PT, CH });