339 lines
23 KiB
React
339 lines
23 KiB
React
/* eslint-disable */
|
||
// ─────────────────────────────────────────────────────────────
|
||
// searchgg · 공용 컴포넌트 (라이트 테마 · 흰 배경 / 검정 포인트)
|
||
// ─────────────────────────────────────────────────────────────
|
||
const { useState, useRef, useEffect } = React;
|
||
|
||
// ── 아이콘 ──
|
||
const PATHS = {
|
||
search: 'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm6 12 4 4',
|
||
chevR: 'M9 5l7 7-7 7',
|
||
chevL: 'M15 5l-7 7 7 7',
|
||
user: 'M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM4 20a8 8 0 0 1 16 0',
|
||
users: 'M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7zM2.5 19a6.5 6.5 0 0 1 13 0M16 4.5a3.5 3.5 0 0 1 0 7M18 13a6.5 6.5 0 0 1 3.5 6',
|
||
bolt: 'M13 2L4 14h6l-1 8 9-12h-6z',
|
||
refresh: 'M20 11a8 8 0 1 0-.7 4.5M20 5v6h-6',
|
||
clock: 'M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 7v5l3.5 2',
|
||
heart: 'M12 20s-7-4.3-7-9.5A3.5 3.5 0 0 1 12 7a3.5 3.5 0 0 1 7 3.5C19 15.7 12 20 12 20z',
|
||
gun: 'M3 8h15l-1 4h-3l-1 3h-3l-1-3H5a2 2 0 0 1-2-2V8zM8 12v3',
|
||
shieldcheck: 'M12 3l7 3v5c0 4.5-3 7.3-7 8.5-4-1.2-7-4-7-8.5V6l7-3zM9 11.5l2 2 4-4',
|
||
flame: 'M12 2c1 3-1.5 4.2-1.5 6.5 0 1.4 1 2.3 1 2.3s.6-1 .6-2.2c1.6 1 3.4 3 3.4 5.6a5.5 5.5 0 1 1-11 0c0-2.3 1.4-4 2.2-5 .3 1 .9 1.6.9 1.6s-.2-2.3 1.2-4.2C10.4 4.6 12 4 12 2z',
|
||
};
|
||
function Icon({ name, size = 18, stroke = 'currentColor', fill = 'none', sw = 1.7, style }) {
|
||
const filled = ['flame', 'bolt', 'heart'].includes(name);
|
||
return (
|
||
<svg width={size} height={size} viewBox="0 0 24 24" fill={filled ? stroke : fill}
|
||
stroke={filled ? 'none' : stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round"
|
||
style={{ flexShrink: 0, ...style }}>
|
||
<path d={PATHS[name]} />
|
||
</svg>
|
||
);
|
||
}
|
||
|
||
// ── 로고 ──
|
||
function Logo({ size = 24, light = false }) {
|
||
return (
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, userSelect: 'none' }}>
|
||
<svg width={size * 1.16} height={size * 1.16} viewBox="0 0 28 28" fill="none">
|
||
<circle cx="14" cy="14" r="9" fill="none" stroke="#48515f" strokeWidth="1.8" />
|
||
<path d="M14 3.5v4M14 20.5v4M3.5 14h4M20.5 14h4" stroke="#48515f" strokeWidth="1.8" strokeLinecap="round" />
|
||
<circle cx="14" cy="14" r="2.1" fill="#48515f" />
|
||
</svg>
|
||
<div style={{ fontFamily: "'Chakra Petch', sans-serif", fontWeight: 700, fontSize: size, letterSpacing: '-0.5px', lineHeight: 1 }}>
|
||
<span style={{ color: light ? '#fff' : '#15171c' }}>search</span><span style={{ color: '#48515f' }}>.gg</span>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ── 계급(랭크) 뱃지 ──
|
||
function RankBadge({ rank, size = 44, showName = false }) {
|
||
if (!rank) return null;
|
||
const c = rank.color;
|
||
const pip = (i) => {
|
||
const cx = size / 2, base = size * 0.66, gap = size * 0.13;
|
||
const total = rank.pips, x = cx + (i - (total - 1) / 2) * gap;
|
||
if (rank.shape === 'star') return <path key={i} d="M0 -2.1 L0.62 -0.65 L2.1 -0.5 L1 0.5 L1.35 2 L0 1.2 L-1.35 2 L-1 0.5 L-2.1 -0.5 L-0.62 -0.65 Z" transform={`translate(${x} ${base}) scale(${size * 0.06})`} fill={c} />;
|
||
if (rank.shape === 'flower') return <circle key={i} cx={x} cy={base} r={size * 0.05} fill={c} />;
|
||
if (rank.shape === 'dia') return <rect key={i} x={x - size * 0.045} y={base - size * 0.045} width={size * 0.09} height={size * 0.09} fill={c} transform={`rotate(45 ${x} ${base})`} />;
|
||
if (rank.shape === 'chev') return <path key={i} d={`M ${x - size * 0.07} ${base + size * 0.05} L ${x} ${base - size * 0.03} L ${x + size * 0.07} ${base + size * 0.05}`} stroke={c} strokeWidth={size * 0.035} fill="none" />;
|
||
return <rect key={i} x={x - size * 0.05} y={base - size * 0.025} width={size * 0.1} height={size * 0.05} rx={size * 0.01} fill={c} />;
|
||
};
|
||
return (
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: showName ? 8 : 0 }}>
|
||
<svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ flexShrink: 0 }}>
|
||
<path d={`M${size / 2} ${size * 0.07} L${size * 0.86} ${size * 0.24} V${size * 0.52} c0 ${size * 0.22}-${size * 0.16} ${size * 0.32}-${size * 0.36} ${size * 0.4} C${size * 0.3} ${size * 0.84}-${0} 0 ${size * 0.14} ${size * 0.52} V${size * 0.24} Z`}
|
||
fill={`${c}16`} stroke={c} strokeWidth="1.4" strokeLinejoin="round" />
|
||
<text x={size / 2} y={size * 0.43} textAnchor="middle" fontFamily="'Pretendard',sans-serif" fontWeight="800" fontSize={size * 0.26} fill={c}>{rank.name}</text>
|
||
{Array.from({ length: rank.pips }).map((_, i) => pip(i))}
|
||
</svg>
|
||
{showName && (
|
||
<div style={{ lineHeight: 1.1 }}>
|
||
<div style={{ fontFamily: "'Chakra Petch',sans-serif", fontWeight: 600, fontSize: 13, color: c }}>{rank.name}</div>
|
||
<div style={{ fontSize: 10.5, color: 'var(--t3)' }}>{rank.group}</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function wrColor(wr) { return wr >= 60 ? '#48515f' : wr >= 50 ? '#48515f' : '#e5484d'; }
|
||
|
||
// ── 승률 링 ──
|
||
function WinRing({ wr, size = 64, sw = 6, label = '승률', color }) {
|
||
const r = (size - sw) / 2, c = 2 * Math.PI * r;
|
||
const col = color || wrColor(wr);
|
||
return (
|
||
<div style={{ position: 'relative', width: size, height: size }}>
|
||
<svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
|
||
<circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="#eceef1" strokeWidth={sw} />
|
||
<circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={col} strokeWidth={sw} strokeLinecap="round"
|
||
strokeDasharray={c} strokeDashoffset={c * (1 - wr / 100)} />
|
||
</svg>
|
||
<div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', textAlign: 'center', lineHeight: 1 }}>
|
||
<div>
|
||
<div style={{ fontFamily: "'Chakra Petch',sans-serif", fontWeight: 700, fontSize: size * 0.28, color: col }}>{wr}<span style={{ fontSize: size * 0.16 }}>%</span></div>
|
||
<div style={{ fontSize: size * 0.13, color: 'var(--t3)', marginTop: 2 }}>{label}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ── KDA 칩 ──
|
||
function KdaChip({ k, d, a, big }) {
|
||
return (
|
||
<span style={{ fontFamily: "'Chakra Petch',sans-serif", fontWeight: 600, fontSize: big ? 16 : 13, letterSpacing: '.3px' }}>
|
||
<span style={{ color: 'var(--ink)' }}>{k}</span>
|
||
<span style={{ color: 'var(--t3)', margin: '0 3px' }}>/</span>
|
||
<span style={{ color: '#e5484d' }}>{d}</span>
|
||
<span style={{ color: 'var(--t3)', margin: '0 3px' }}>/</span>
|
||
<span style={{ color: '#48515f' }}>{a}</span>
|
||
</span>
|
||
);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// SearchBar — 흰 필드 + 검정 버튼. 라이브 추천 → onPick(player)
|
||
// ─────────────────────────────────────────────────────────────
|
||
function SearchBar({ onPick, big, placeholder = '닉네임으로 전적을 검색하세요' }) {
|
||
const SA = window.SA;
|
||
const [q, setQ] = useState('');
|
||
const [open, setOpen] = useState(false);
|
||
const ref = useRef(null);
|
||
useEffect(() => {
|
||
const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
|
||
document.addEventListener('pointerdown', h, true);
|
||
return () => document.removeEventListener('pointerdown', h, true);
|
||
}, []);
|
||
const matches = q.trim()
|
||
? SA.allPlayers.filter((p) => p.name.toLowerCase().includes(q.trim().toLowerCase())).slice(0, 6)
|
||
: [];
|
||
const recents = SA.recentSearches.map((n) => SA.allPlayers.find((p) => p.name === n)).filter(Boolean);
|
||
const submit = () => {
|
||
const found = matches[0] || SA.allPlayers.find((p) => p.name === q.trim());
|
||
if (found) { onPick(found); setQ(''); setOpen(false); }
|
||
else if (q.trim()) { onPick(SA.allPlayers[1]); setQ(''); setOpen(false); }
|
||
};
|
||
const h = big ? 58 : 44;
|
||
return (
|
||
<div ref={ref} style={{ position: 'relative', width: '100%' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', height: h, background: '#fff',
|
||
border: `1.5px solid ${open ? '#48515f' : 'var(--line2)'}`, borderRadius: 4,
|
||
boxShadow: open ? '0 6px 22px rgba(0,0,0,.10)' : '0 1px 2px rgba(0,0,0,.04)',
|
||
transition: 'border-color .14s, box-shadow .14s', overflow: 'hidden' }}>
|
||
<div style={{ paddingLeft: big ? 18 : 13, color: open ? '#48515f' : 'var(--t3)', display: 'flex' }}>
|
||
<Icon name="search" size={big ? 22 : 18} sw={2} />
|
||
</div>
|
||
<input value={q} onChange={(e) => { setQ(e.target.value); setOpen(true); }} onFocus={() => setOpen(true)}
|
||
onKeyDown={(e) => e.key === 'Enter' && submit()} placeholder={placeholder}
|
||
style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', color: '#15171c',
|
||
fontFamily: "'Pretendard',sans-serif", fontSize: big ? 17 : 14.5, padding: `0 ${big ? 16 : 11}px`, fontWeight: 500 }} />
|
||
<button onClick={submit} style={{ height: '100%', border: 'none', cursor: 'pointer', color: '#fff',
|
||
background: '#15171c', fontFamily: "'Chakra Petch',sans-serif", fontWeight: 700, fontSize: big ? 15 : 13,
|
||
padding: `0 ${big ? 26 : 17}px`, letterSpacing: '.5px' }}>검색</button>
|
||
</div>
|
||
{open && (
|
||
<div style={{ position: 'absolute', top: h + 8, left: 0, right: 0, background: '#fff',
|
||
border: '1px solid var(--line)', borderRadius: 4, boxShadow: '0 16px 40px rgba(20,22,28,.12)',
|
||
padding: 7, zIndex: 40, overflow: 'hidden', textAlign: 'left' }}>
|
||
<div style={{ fontSize: 11, fontWeight: 700, color: 'var(--t3)', padding: '6px 10px 8px', letterSpacing: '.3px' }}>
|
||
{q.trim() ? `"${q}" 검색 결과` : '최근 검색한 유저'}
|
||
</div>
|
||
{(q.trim() ? matches : recents).map((p) => (
|
||
<button key={p.name} onClick={() => { onPick(p); setQ(''); setOpen(false); }}
|
||
style={{ display: 'flex', alignItems: 'center', gap: 12, width: '100%', border: 'none', background: 'transparent',
|
||
padding: '8px 10px', borderRadius: 4, cursor: 'pointer', textAlign: 'left', transition: 'background .12s' }}
|
||
onMouseEnter={(e) => e.currentTarget.style.background = '#f5f6f8'}
|
||
onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
|
||
<RankBadge rank={p.rank} size={32} />
|
||
<div style={{ flex: 1, minWidth: 0 }}>
|
||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
|
||
<span style={{ color: '#15171c', fontWeight: 600, fontSize: 14, flexShrink: 0, maxWidth: '62%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</span>
|
||
{p.clan && <span style={{ fontSize: 11, color: 'var(--t2)', fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.clan}</span>}
|
||
</div>
|
||
<div style={{ fontSize: 11.5, color: 'var(--t3)' }}>{p.rank.name} · Lv.{p.level} · 승률 {p.wr}%</div>
|
||
</div>
|
||
<Icon name="chevR" size={15} stroke="var(--t3)" />
|
||
</button>
|
||
))}
|
||
{q.trim() && matches.length === 0 && (
|
||
<div style={{ padding: '14px 10px', color: 'var(--t3)', fontSize: 13 }}>일치하는 유저가 없어요. 닉네임을 확인해 주세요.</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ── 최근검색 칩 ──
|
||
function RecentChips({ onPick, onDark = false }) {
|
||
const SA = window.SA;
|
||
return (
|
||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>
|
||
<span style={{ fontSize: 12, color: onDark ? 'rgba(255,255,255,.55)' : 'var(--t3)', display: 'flex', alignItems: 'center', gap: 5 }}>
|
||
<Icon name="clock" size={13} /> 최근
|
||
</span>
|
||
{SA.recentSearches.slice(0, 6).map((n) => {
|
||
const p = SA.allPlayers.find((x) => x.name === n);
|
||
return (
|
||
<button key={n} onClick={() => p && onPick(p)}
|
||
style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '5px 12px 5px 9px', borderRadius: 4,
|
||
background: onDark ? 'rgba(255,255,255,.08)' : '#fff', border: `1px solid ${onDark ? 'rgba(255,255,255,.16)' : 'var(--line2)'}`, cursor: 'pointer',
|
||
color: onDark ? '#e7eaee' : '#3a4049', fontSize: 12.5, fontWeight: 500, transition: 'all .12s', fontFamily: "'Pretendard',sans-serif" }}
|
||
onMouseEnter={(e) => { e.currentTarget.style.borderColor = onDark ? '#fff' : '#15171c'; }}
|
||
onMouseLeave={(e) => { e.currentTarget.style.borderColor = onDark ? 'rgba(255,255,255,.16)' : 'var(--line2)'; }}>
|
||
{n}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// 문의 위젯 — 우하단 플로팅 버튼 + 문의 모달
|
||
// 푸터 '문의하기' 링크는 window 'sa-open-feedback' 이벤트로 연동
|
||
// ─────────────────────────────────────────────────────────────
|
||
function FeedbackWidget() {
|
||
const PT = '#48515f';
|
||
const [open, setOpen] = React.useState(false);
|
||
const [type, setType] = React.useState('불편 사항');
|
||
const [text, setText] = React.useState('');
|
||
const [sent, setSent] = React.useState(false);
|
||
const [files, setFiles] = React.useState([]);
|
||
const fileRef = React.useRef(null);
|
||
const addFiles = (list) => {
|
||
const arr = Array.from(list || []);
|
||
if (!arr.length) return;
|
||
setFiles((f) => [...f, ...arr].slice(0, 3));
|
||
};
|
||
const fmtSize = (n) => n > 1048576 ? (n / 1048576).toFixed(1) + 'MB' : Math.max(1, Math.round(n / 1024)) + 'KB';
|
||
React.useEffect(() => {
|
||
const fn = () => { setOpen(true); setSent(false); };
|
||
window.addEventListener('sa-open-feedback', fn);
|
||
return () => window.removeEventListener('sa-open-feedback', fn);
|
||
}, []);
|
||
const submit = () => {
|
||
if (!text.trim()) return;
|
||
setSent(true);
|
||
setTimeout(() => { setOpen(false); setText(''); setType('불편 사항'); setSent(false); setFiles([]); }, 1400);
|
||
};
|
||
return (
|
||
<React.Fragment>
|
||
{/* 플로팅 버튼 */}
|
||
<button onClick={() => { setOpen(true); setSent(false); }} title="문의하기"
|
||
style={{ position: 'fixed', right: 22, bottom: 22, zIndex: 290, display: 'flex', alignItems: 'center', gap: 7, padding: '12px 18px', borderRadius: 26, border: 'none', cursor: 'pointer',
|
||
background: '#20242b', color: '#fff', fontWeight: 700, fontSize: 13, fontFamily: "'Pretendard',sans-serif", boxShadow: '0 6px 22px rgba(0,0,0,.25)' }}>
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||
<path d="M21 11.5a8.4 8.4 0 0 1-9 8.4 8.6 8.6 0 0 1-3.8-.9L3 20l1-4.9a8.4 8.4 0 1 1 17-3.6z" />
|
||
</svg>
|
||
문의
|
||
</button>
|
||
|
||
{/* 문의 모달 */}
|
||
{open && (
|
||
<div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, zIndex: 300, background: 'rgba(20,22,26,.55)', backdropFilter: 'blur(2px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20, animation: 'sgFade .18s ease' }}>
|
||
<div onClick={(e) => e.stopPropagation()} style={{ width: 430, maxWidth: '100%', background: '#fff', borderRadius: 12, overflow: 'hidden', boxShadow: '0 24px 70px rgba(0,0,0,.3)', fontFamily: "'Pretendard',sans-serif" }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '14px 18px', borderBottom: '1px solid var(--line)' }}>
|
||
<div>
|
||
<div style={{ fontSize: 15, fontWeight: 800, color: 'var(--ink)' }}>문의하기</div>
|
||
<div style={{ fontSize: 11.5, color: 'var(--t3)', marginTop: 2 }}>불편한 점이나 궁금한 점을 알려주세요.</div>
|
||
</div>
|
||
<button onClick={() => setOpen(false)} style={{ width: 28, height: 28, borderRadius: 6, border: 'none', background: '#eef0f2', color: '#5b626c', cursor: 'pointer', fontSize: 15 }}>×</button>
|
||
</div>
|
||
|
||
{sent ? (
|
||
<div style={{ padding: '38px 18px', textAlign: 'center' }}>
|
||
<div style={{ width: 44, height: 44, borderRadius: '50%', background: `${PT}14`, display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}>
|
||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={PT} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5l4.5 4.5L19 7.5" /></svg>
|
||
</div>
|
||
<div style={{ fontSize: 14.5, fontWeight: 800, color: 'var(--ink)' }}>문의가 접수되었어요</div>
|
||
<div style={{ fontSize: 12.5, color: 'var(--t2)', marginTop: 4 }}>답변은 마이페이지 > 문의 내역에서 확인할 수 있어요.</div>
|
||
</div>
|
||
) : (
|
||
<div style={{ padding: '16px 18px' }}>
|
||
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--t2)', marginBottom: 7 }}>문의 유형</div>
|
||
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 14 }}>
|
||
{['불편 사항', '버그 제보', '기능 제안', '신고', '기타 문의'].map((v) => {
|
||
const on = type === v;
|
||
return (
|
||
<button key={v} onClick={() => setType(v)} style={{ padding: '6px 12px', borderRadius: 5, cursor: 'pointer', fontFamily: "'Pretendard',sans-serif", fontWeight: 700, fontSize: 12,
|
||
border: `1px solid ${on ? PT : 'var(--line2)'}`, background: on ? PT : '#fff', color: on ? '#fff' : 'var(--t2)' }}>{v}</button>
|
||
);
|
||
})}
|
||
</div>
|
||
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--t2)', marginBottom: 7 }}>내용</div>
|
||
<textarea value={text} onChange={(e) => setText(e.target.value)} rows={5} placeholder="어떤 점이 불편했는지, 어떤 기능이 궁금한지 자유롭게 적어주세요."
|
||
style={{ width: '100%', resize: 'vertical', padding: '10px 12px', border: '1px solid var(--line2)', borderRadius: 7, fontSize: 13, lineHeight: 1.6, fontFamily: "'Pretendard',sans-serif", color: '#3a4049', outline: 'none', boxSizing: 'border-box', marginBottom: 6 }} />
|
||
<div style={{ fontSize: 11.5, color: 'var(--t3)', marginBottom: 14 }}>답변은 로그인한 계정의 <b style={{ color: 'var(--t2)' }}>마이페이지 > 문의 내역</b>으로 드려요.</div>
|
||
|
||
{/* 파일 첨부 */}
|
||
<input ref={fileRef} type="file" multiple accept="image/*,video/*,.log,.txt" style={{ display: 'none' }} onChange={(e) => { addFiles(e.target.files); e.target.value = ''; }} />
|
||
<div style={{ marginBottom: 14 }}>
|
||
<button onClick={() => fileRef.current && fileRef.current.click()} disabled={files.length >= 3}
|
||
style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 13px', borderRadius: 7, cursor: files.length >= 3 ? 'not-allowed' : 'pointer', background: '#fff', border: '1px dashed var(--line2)', color: files.length >= 3 ? 'var(--t3)' : 'var(--t2)', fontWeight: 700, fontSize: 12, fontFamily: "'Pretendard',sans-serif" }}>
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21.4 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
|
||
파일 첨부 <span style={{ fontWeight: 600, color: 'var(--t3)' }}>({files.length}/3)</span>
|
||
</button>
|
||
{files.length > 0 && (
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5, marginTop: 8 }}>
|
||
{files.map((f, i) => (
|
||
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 10px', background: '#f7f8f9', border: '1px solid var(--line)', borderRadius: 6 }}>
|
||
<span style={{ flex: 1, minWidth: 0, fontSize: 12, fontWeight: 600, color: 'var(--ink)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</span>
|
||
<span style={{ fontSize: 10.5, color: 'var(--t3)', flexShrink: 0 }}>{fmtSize(f.size)}</span>
|
||
<button onClick={() => setFiles(files.filter((_, j) => j !== i))} style={{ border: 'none', background: 'transparent', cursor: 'pointer', color: 'var(--t3)', fontSize: 14, lineHeight: 1, padding: 0, flexShrink: 0 }}>×</button>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
<button onClick={submit} disabled={!text.trim()} style={{ width: '100%', padding: '12px 0', borderRadius: 7, border: 'none', background: text.trim() ? PT : '#c4c8ce', color: '#fff', fontWeight: 700, fontSize: 14, cursor: text.trim() ? 'pointer' : 'not-allowed', fontFamily: "'Pretendard',sans-serif" }}>보내기</button>
|
||
|
||
{/* 비회원 문의 채널 */}
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 10, margin: '16px 0 11px' }}>
|
||
<span style={{ flex: 1, height: 1, background: 'var(--line)' }} />
|
||
<span style={{ fontSize: 11, color: 'var(--t3)', fontWeight: 600 }}>계정 없이 이용 중이신가요?</span>
|
||
<span style={{ flex: 1, height: 1, background: 'var(--line)' }} />
|
||
</div>
|
||
<div style={{ display: 'flex', gap: 8 }}>
|
||
<button style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7, padding: '10px 0', borderRadius: 7, border: 'none', cursor: 'pointer', background: '#5865F2', color: '#fff', fontWeight: 700, fontSize: 12.5, fontFamily: "'Pretendard',sans-serif" }}>
|
||
<svg width="15" height="15" viewBox="0 0 24 24" fill="#fff"><path d="M19.6 5.6A17.3 17.3 0 0 0 15.4 4l-.5 1a16 16 0 0 0-5.8 0l-.5-1a17.3 17.3 0 0 0-4.2 1.6C1.7 9.6 1 13.5 1.3 17.3A17.5 17.5 0 0 0 6.6 20l1.1-1.8a11 11 0 0 1-1.7-.9l.4-.3a12.4 12.4 0 0 0 11.2 0l.4.3c-.5.4-1.1.7-1.7.9L17.4 20a17.4 17.4 0 0 0 5.3-2.7c.4-4.4-.7-8.2-3.1-11.7zM8.7 14.9c-1 0-1.9-1-1.9-2.1s.8-2.1 1.9-2.1 1.9 1 1.9 2.1-.9 2.1-1.9 2.1zm6.6 0c-1 0-1.9-1-1.9-2.1s.9-2.1 1.9-2.1 1.9 1 1.9 2.1-.8 2.1-1.9 2.1z"/></svg>
|
||
디스코드 문의
|
||
</button>
|
||
<button style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7, padding: '10px 0', borderRadius: 7, border: 'none', cursor: 'pointer', background: '#FEE500', color: '#191600', fontWeight: 700, fontSize: 12.5, fontFamily: "'Pretendard',sans-serif" }}>
|
||
<svg width="15" height="15" viewBox="0 0 24 24" fill="#191600"><path d="M12 3C6.5 3 2 6.5 2 10.8c0 2.7 1.8 5.1 4.5 6.5l-1 3.8c-.1.4.3.7.6.5l4.4-2.9c.5.1 1 .1 1.5.1 5.5 0 10-3.5 10-7.9S17.5 3 12 3z"/></svg>
|
||
카카오톡 문의
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
Object.assign(window, { Icon, Logo, RankBadge, WinRing, KdaChip, SearchBar, RecentChips, wrColor, FeedbackWidget });
|