/* eslint-disable */
// ─────────────────────────────────────────────────────────────
// searchgg · 클랜홈 섹션 컴포넌트 (브랜드 컬러 고정)
// 의존: window.Panel, Icon, RankBadge, Emblem, SA
// ─────────────────────────────────────────────────────────────
const CLPT = '#48515f';
const CLCH = "'Chakra Petch',sans-serif";
function RoleBadge({ role, theme }) {
const map = {
'클랜장': { bg: theme, color: '#fff' },
'운영진': { bg: `${theme}22`, color: theme },
'정예': { bg: '#eef0f2', color: '#5b626c' },
'일반': { bg: 'transparent', color: '#949aa3' },
};
const s = map[role] || map['일반'];
return {role};
}
// ── 멤버 ──
function ClanMembers({ clan, onPick }) {
const groups = ['클랜장', '운영진', '정예', '일반'];
const byRole = (r) => clan.members.filter((m) => m.role === r);
return (
{clan.totalMembers} / {clan.memberMax}명} bodyPad="6px 0 6px">
{groups.map((g) => {
const list = byRole(g);
if (!list.length) return null;
return (
{g} · {list.length}
기여도
{list.map((m, i) => (
))}
);
})}
);
}
// ── 정기전 일정 ──
function ClanSchedule({ clan }) {
const t = CLPT;
const [items, setItems] = React.useState(clan.schedule);
const [open, setOpen] = React.useState(false);
const [day, setDay] = React.useState('월');
const [time, setTime] = React.useState('21:00');
const [title, setTitle] = React.useState('');
React.useEffect(() => { setItems(clan.schedule); setOpen(false); }, [clan.name]);
const register = () => {
const name = title.trim();
if (!name) return;
setItems(items.map((s) => s.day === day ? { ...s, on: true, time, title: name } : s));
setTitle('');
setOpen(false);
};
const remove = (d) => setItems(items.map((s) => s.day === d ? { ...s, on: false, time: '—', title: '휴식' } : s));
const inputStyle = { border: '1px solid var(--line2)', borderRadius: 6, padding: '9px 11px', fontSize: 13, fontFamily: "'Pretendard',sans-serif", fontWeight: 600, color: 'var(--ink)', outline: 'none', boxSizing: 'border-box' };
return (
setOpen(true)} style={{ border: 'none', background: 'transparent', cursor: 'pointer', fontFamily: "'Pretendard',sans-serif", fontWeight: 700, fontSize: 12, color: t, padding: 0 }}>+ 일정 등록
) : null} bodyPad="12px 14px 14px">
{items.filter((s) => s.on).map((s) => (
{s.day}
{s.time}
{s.title}
{clan.isMine && (
)}
))}
{items.every((s) => !s.on) &&
등록된 일정이 없어요.
}
{/* 일정 등록 모달 */}
{open && (
setOpen(false)} style={{ position: 'fixed', inset: 0, zIndex: 260, background: 'rgba(20,22,26,.55)', backdropFilter: 'blur(2px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20, animation: 'sgFade .18s ease' }}>
e.stopPropagation()} style={{ width: 380, maxWidth: '100%', background: '#fff', borderRadius: 12, overflow: 'hidden', boxShadow: '0 24px 70px rgba(0,0,0,.3)', fontFamily: "'Pretendard',sans-serif" }}>
일정 등록
요일
{items.map((s) => (
))}
{items.find((s) => s.day === day && s.on) && (
이미 일정이 있는 요일이에요. 등록하면 덮어써요.
)}
)}
);
}
// ── 주간 활동 (접속률) ──
function ClanActivity({ clan }) {
const days = ['월', '화', '수', '목', '금', '토', '일'];
const max = Math.max(...clan.attendance);
return (
접속률} bodyPad="14px 14px 12px">
{clan.attendance.map((v, i) => (
))}
);
}
// ── 주간 매치 (모드별) ──
function ClanWeeklyMatches({ clan }) {
const days = ['월', '화', '수', '목', '금', '토', '일'];
const acts = clan.activity;
const cats = [
['clanWar', '클랜전', CLPT],
['clanRanked', '클랜 랭크전', '#6b7585'],
['soloRanked', '솔로 랭크전', '#99a1ae'],
['partyRanked', '파티 랭크전', '#cdd2d9'],
];
const sum = (a) => cats.reduce((s, [k]) => s + a[k], 0);
const max = Math.max(...acts.map(sum));
const totals = cats.map(([k, label, color]) => [label, acts.reduce((s, a) => s + a[k], 0), color]);
return (
모드별 판수} bodyPad="14px 14px 12px">
{acts.map((a, i) => (
{sum(a)}
{cats.map(([k, label, color]) => (
))}
{days[i]}
))}
{totals.map(([label, n, color]) => (
{label} {n}판
))}
);
}
// ── 미니 페이저 ──
function ClanPager({ page, total, onPage }) {
if (total <= 1) return null;
const nav = (dis) => ({ width: 26, height: 26, borderRadius: 5, border: '1px solid var(--line2)', background: '#fff', cursor: dis ? 'default' : 'pointer', opacity: dis ? .4 : 1, display: 'grid', placeItems: 'center' });
return (
{Array.from({ length: total }, (_, i) => i + 1).map((n) => (
))}
);
}
// ── 공지 ──
function ClanNotices({ clan }) {
const PER = 4;
const [page, setPage] = React.useState(1);
React.useEffect(() => setPage(1), [clan.name]);
const total = Math.max(1, Math.ceil(clan.notices.length / PER));
const cur = Math.min(page, total);
const rows = clan.notices.slice((cur - 1) * PER, cur * PER);
return (
{rows.map((n, i) => (
{n.pin && 고정}
{n.title}
{n.author} · {n.time}
))}
setPage(Math.max(1, Math.min(total, n)))} />
);
}
// ── 클랜 피드 ──
function ClanFeed({ clan }) {
const PER = 3;
const [items, setItems] = React.useState(clan.feed);
const [draft, setDraft] = React.useState('');
const [page, setPage] = React.useState(1);
React.useEffect(() => { setItems(clan.feed); setDraft(''); setPage(1); }, [clan.name]);
const total = Math.max(1, Math.ceil(items.length / PER));
const cur = Math.min(page, total);
const rows = items.slice((cur - 1) * PER, cur * PER);
const post = () => {
const text = draft.trim();
if (!text) return;
setItems([{ author: window.SA.me.name, role: '일반', time: '방금 전', text, likes: 0 }, ...items]);
setDraft('');
setPage(1);
};
return (
{clan.isMine && (
)}
{rows.map((f, i) => (
{f.author.slice(0, 1)}
{f.author}
{f.time}
{f.text}
{f.likes}
))}
setPage(Math.max(1, Math.min(total, n)))} />
);
}
// ── 방명록 ──
function ClanGuestbook({ clan }) {
const PER = 4;
const [items, setItems] = React.useState(clan.guestbook);
const [draft, setDraft] = React.useState('');
const [page, setPage] = React.useState(1);
React.useEffect(() => { setItems(clan.guestbook); setDraft(''); setPage(1); }, [clan.name]);
const total = Math.max(1, Math.ceil(items.length / PER));
const cur = Math.min(page, total);
const rows = items.slice((cur - 1) * PER, cur * PER);
const post = () => {
const text = draft.trim();
if (!text) return;
setItems([{ author: window.SA.me.name, text, time: '방금 전' }, ...items]);
setDraft('');
setPage(1);
};
const [replyAt, setReplyAt] = React.useState(-1);
const [replyDraft, setReplyDraft] = React.useState('');
React.useEffect(() => { setReplyAt(-1); setReplyDraft(''); }, [clan.name]);
const postReply = (gi) => {
const text = replyDraft.trim();
if (!text) return;
setItems(items.map((g, idx) => idx === gi ? { ...g, replies: [...(g.replies || []), { author: window.SA.me.name, text, time: '방금 전' }] } : g));
setReplyDraft('');
setReplyAt(-1);
};
return (
클랜원은 답글만 달 수 있어요 : null} bodyPad="10px 14px 14px">
{!clan.isMine && (
setDraft(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') post(); }} placeholder="따뜻한 한마디를 남겨보세요" style={{ flex: 1, minWidth: 0, border: '1px solid var(--line2)', borderRadius: 6, padding: '9px 12px', fontSize: 13, fontFamily: "'Pretendard',sans-serif", outline: 'none' }} />
)}
{rows.map((g, i) => {
const gi = (cur - 1) * PER + i;
const replies = g.replies || [];
return (
{g.author.slice(0, 1)}
{g.author}
{g.time}
{clan.isMine && (
)}
{g.text}
{/* 답글 목록 */}
{replies.map((rp, j) => (
{rp.author.slice(0, 1)}
{rp.author}
클랜원
{rp.time}
{rp.text}
))}
{/* 답글 입력 */}
{replyAt === gi && (
setReplyDraft(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') postReply(gi); }} placeholder="답글을 남겨보세요"
style={{ flex: 1, minWidth: 0, border: '1px solid var(--line2)', borderRadius: 6, padding: '7px 10px', fontSize: 12.5, fontFamily: "'Pretendard',sans-serif", outline: 'none' }} />
)}
);
})}
setPage(Math.max(1, Math.min(total, n)))} />
);
}
Object.assign(window, { ClanMembers, ClanSchedule, ClanActivity, ClanWeeklyMatches, ClanNotices, ClanFeed, ClanGuestbook });