/* ===================================================================== * Afflix Subscriber SaaS — v2 보강 (디팀 v2.0 · 2026-05-08) * --------------------------------------------------------------------- * 정본 기준: 감사_구독자SaaS_2차보강_디팀전달안_20260508.md * 변경: * · Shell — 어드민형 독립 스크롤 구조 (.saas-shell height:100vh) * · Shell — 로고 하단 구분선 제거 (검색바 라인과 미세 어긋남 시정) * · 관리 4화면 모두 활성화 (sub/pay/use/set) — 2차 뱃지 → 활성 * · 2차 이후 후보 4개(prog/blog/ref/help) — 곧 출시 비활성 항목으로 노출 * · Dashboard — 구독 스트립 + 최근 결과 + 오늘 할 일 카드 추가 * · NEW: SaasSubscription (구독 상태 대시보드) * · NEW: SaasBilling (FREE/BASIC/PRO 비교 + 청구 이력 6건) * · NEW: SaasQuota (이번 달 발행/한도 + 30일 sparkline + 미니 카드 3종) * · NEW: SaasSettings (발행 알림·시간대·기본값·계정) * 의존: v12/thumb-t01a.jsx, v12/saas-screens.jsx (v1 base 위 override) * ===================================================================== */ const { useState: u2, useMemo: m2 } = React; // 2026-05-25 F10-⑤ P0 (CFO 결재 ⑤ 정합): 가상 사용자 demo data 명시 라벨 // 본 객체는 실 사용자 가입 전 SaaS UI 미리보기·시연용 데모 데이터. // F2 (회원 가입 ID/PW) LIVE 후 실 사용자 분기로 교체될 예정. // 화면 상단에 "🧪 운영 예시 모드" 배지 노출 의무 (감사 결재 5/25). const SAAS_USER2 = { name:'운영 예시', plan:'Basic · 1개월 무료', plan_kind:'basic_trial', trial_end:'2026-06-07', days_left:30, month_publish:142, quota:300, recent_revenue:'₩2,840,000', publish_today:1, publish_yesterday:1, card_registered:false, next_billing:null, email:'demo@afflix.com', is_demo:true, // F10-⑤ 가상 사용자 명시 (감사 결재) demo_label:'🧪 운영 예시 모드', // 화면 배지 표시 데이터 demo_disclaimer:'본 화면은 운영 예시 데모 데이터입니다. 실제 발행·결제·수치 아님.', }; // 2026-05-26 2기 개발팀장 정정 (CFO 결재 ⑤ P0 마감 라운드): // - name '정태우' → '운영 예시' (감사 결재 5/25 의무 적용) // - email 'taewoo@afflix.com' → 'demo@afflix.com' // - 잔여: 화면 상단 배지 노출 (Shell render) 별건 점검 후 진행 // LIVE wrapper 정합 (saas-data-runtime.js가 mutation) · 디팀 v3.10 정본 시 디팀 직접 추가 권고 window.SAAS_USER2 = SAAS_USER2; /* ===== 공통 셸 v2 ===== */ window.SaasShell = function({ route, setRoute, children, theme, setTheme, onLogout }){ const menu = [ { id:'home', label:'대시보드', sub:'오늘 할 일 · 최근 결과', emoji:'🏠' }, { id:'setup', label:'발행 설정', sub:'AI 자동 · 키워드 · 시간대', emoji:'🚀' }, { id:'grid', label:'템플릿 패키지', sub:'카테고리별 템플릿 모음', emoji:'📦' }, { id:'perf', label:'성과 참고', sub:'발행량 · 반응 · 인기 글', emoji:'📈' }, ]; const mgmt = [ { id:'sub', label:'내 구독', sub:'플랜 · 남은 기간 · 현재 상태', emoji:'💎' }, { id:'pay', label:'결제·플랜', sub:'결제수단 · 결제내역 · 플랜 변경', emoji:'💳' }, { id:'use', label:'사용량', sub:'이번 달 발행량 · 남은 한도', emoji:'📊' }, { id:'set', label:'설정', sub:'알림 · 외부 연동 · 보안', emoji:'⚙️' }, ]; // 2차 이후 후보(진행현황/내 블로그/레퍼럴/1:1문의) — 정본 §5 — 좌측 메뉴에 미리 노출 X return (
{SAAS_USER2.is_demo && (
{SAAS_USER2.demo_label} · {SAAS_USER2.demo_disclaimer}
)} {/* F5-⑤ 사용량 progress bar (CFO 결재 2C · 3 위치 통일 — 대시보드 양식) */}
📊 이번 달 사용량
=0.9?'#EF4444':(SAAS_USER2.month_publish/SAAS_USER2.quota)>=0.7?'#F59E0B':'#10B981',transition:'width 300ms'}}/>
{SAAS_USER2.month_publish} / {SAAS_USER2.quota} ({SAAS_USER2.plan_kind === 'basic_trial' ? '무료 체험' : SAAS_USER2.plan})
{children}
); }; /* ===== Dashboard v2 — 구독 스트립 + 최근 결과 + 오늘 할 일 ===== */ const _DashV1 = window.SaasDashboard; window.SaasDashboard = function(props){ const u = SAAS_USER2; return (
{/* 구독 상태 스트립 */}
{u.plan} {u.trial_end}까지 · 남은 {u.days_left}일 {/* F4-B-1 (2026-05-27 · CFO 결재 1-A·B 직렬 정합): 현재 phase + 다음 진입일 */} {u.phase && ( 현재: { u.phase === 'trial' ? '무료 체험' : u.phase === 'setup' ? '셋업 (30% 할인)' : u.phase === 'normal' ? '정상가' : u.phase === 'contract' ? '약정 (25% 할인)' : u.phase } {u.phase_days_from_start != null && · D+{u.phase_days_from_start}} {u.next_phase_at && · 다음: {u.next_phase_at.slice(0,10)}} )} 이번 달 발행 {u.month_publish} / {u.quota} · 어제 자동 발행 {u.publish_yesterday}건
<_DashV1 {...props}/> {/* 오늘 할 일 + 최근 결과 */}

오늘 할 일

결제 수단을 등록하면 1개월 이후에도 끊김 없이 발행돼요 남은 13일 — 등록은 1분이면 끝
어제 발행 1건이 인기 글에 진입했어요 · CTR 6.4% T01_A · 전자 · 가성비 · 반응 +218
발행 시간을 1개 더 추가하면 한 달 +30건이 가능해요 현재 09:00 1회 → 09:00·15:00 2회 권장
); }; /* ===== NEW · 내 구독 (구독 상태 대시보드) ===== */ window.SaasSubscription = function({ go }){ const u = SAAS_USER2; const used_pct = u.month_publish / u.quota * 100; return (
관리

내 구독

지금 발행 가능한 상태인지, 며칠 남았는지 한 화면에서 확인하세요.

가입일 2026-05-07 다음 결제 {u.card_registered? '2026-06-07' : '미예정'}
{u.plan} ● 정상 발행 중
{u.trial_end}까지 — {u.days_left}일 남았어요
{u.month_publish} / {u.quota}
이번 달 발행
{u.publish_yesterday}
어제 자동 발행
{u.recent_revenue}
최근 30일 수익

발행 상태

📝
자동 발행 활성
매일 09:00 · 카테고리 전자 · 템플릿 T01_A
정상
🔗
티스토리 연동
taewoo.tistory.com · 토큰 만료 2026-08-12
정상
💳
{u.card_registered?'결제 수단 등록 완료':'결제 수단 미등록'}
{u.card_registered?'마스터카드 ****-1234':'1개월 후 발행이 일시 정지될 수 있어요'}
{u.card_registered?'정상':'주의'}
🔔
알림 이메일 미설정
발행 결과를 매일 아침 받아볼 수 있어요
미설정

최근 발행 5건

    {[ { d:'05-07', t:'09:00', name:'T01_A', cat:'전자', ctr:6.4, react:218, top:true }, { d:'05-06', t:'09:00', name:'T01_A', cat:'전자', ctr:5.8, react:184 }, { d:'05-05', t:'09:00', name:'T03_A', cat:'전자', ctr:5.2, react:142 }, { d:'05-04', t:'09:00', name:'T01_A', cat:'생활', ctr:4.9, react:128 }, { d:'05-03', t:'09:00', name:'T02_A', cat:'뷰티', ctr:4.4, react:96 }, ].map((r,i)=>(
  • {r.d} {r.t}
    {r.name}
    {r.cat}
    {r.ctr}%
    {r.react} 반응
  • ))}
); }; /* ===== NEW · 결제·플랜 (FREE/BASIC/PRO 비교 + 청구 이력 6건) ===== */ window.SaasBilling = function({ go }){ // 정본 §4 — Basic / Standard / Premium · 1개월 무료 통일 · 보수적 표현 const plans = [ { kind:'basic', name:'Basic', price:'₩99,000', cycle:'/ 월', tagline:'개인 운영자 1인 1블로그 시작 단계.', feats:[ ['월 발행량 — 베이스라인 누적 후 확정', true], ['카테고리 1개 운영', true], ['검증 템플릿 10종', true], ['이메일 알림', true], ['우선 기술 지원', false], ], cta:'현재 사용 중 (1개월 무료)', current:true }, { kind:'standard', name:'Standard', price:'₩199,000', cycle:'/ 월', tagline:'안정 운영 단계 · 다중 카테고리.', popular:true, feats:[ ['월 발행량 — 추정 Basic ×1.5~2', true], ['카테고리 2~3개 운영', true], ['검증 템플릿 10종 사용', true], ['이메일 + 슬랙 알림', true], ['우선 기술 지원', false], ], cta:'Standard로 전환' }, { kind:'premium', name:'Premium', price:'₩399,000', cycle:'/ 월', tagline:'전업 운영 · 우선 기술 지원 포함.', feats:[ ['월 발행량 — 추정 Standard ×2 이상', true], ['카테고리 무제한 운영', true], ['검증 템플릿 10종 + 베타', true], ['이메일 + 슬랙 + 카카오톡', true], ['우선 기술 지원 (영업일 24h)', true], ], cta:'Premium으로 전환' }, ]; const bills = [ { date:'2026-05-07', plan:'Basic', amt:'₩0', method:'—', st:'paid', label:'1개월 무료 체험 시작' }, { date:'2026-04-07', plan:'Standard', amt:'₩199,000', method:'**** 1234', st:'paid', label:'정기 결제' }, { date:'2026-03-07', plan:'Standard', amt:'₩199,000', method:'**** 1234', st:'paid', label:'정기 결제' }, { date:'2026-02-07', plan:'Basic', amt:'₩99,000', method:'**** 1234', st:'paid', label:'정기 결제' }, { date:'2026-01-07', plan:'Basic', amt:'₩99,000', method:'**** 1234', st:'paid', label:'정기 결제' }, { date:'2025-12-07', plan:'Basic', amt:'₩99,000', method:'**** 1234', st:'failed', label:'결제 실패' }, ]; return (
관리

결제·플랜

지금 내 상황에 무엇이 더 맞는지 — 사용량 기준으로 골라보세요.

현재 플랜 {SAAS_USER2.plan} 다음 결제 미예정

플랜 비교

{plans.map(p => (
{p.name}
{p.price} {p.cycle}
{p.tagline}
    {p.feats.map(([t,on],i)=>
  • {t}
  • )}
{p.current ? : }
))}

결제 수단

등록된 결제 수단이 없습니다 1개월 무료 종료 전에 카드를 등록해야 발행이 끊기지 않아요. 색인·SEO 누적 3개월 = 첫 안정 수익 구간 진입.

청구 이력

최근 6건 ·
{bills.map((b,i)=>( ))}
일자플랜금액수단상태영수증
{b.date} {b.plan} {b.amt} {b.method} {b.label}
); }; /* ===== NEW · 사용량·쿼터 ===== */ window.SaasQuota = function({ go }){ const u = SAAS_USER2; const pct = Math.round(u.month_publish/u.quota*100); // 30일 sparkline (mock) const days = [3,4,3,5,4,3,6,5,4,5,6,5,4,3,5,6,7,5,4,5,6,5,4,5,6,7,6,5,4,1]; const max = Math.max(...days); return (
관리

사용량·쿼터

이번 달 얼마나 썼는지, 언제 한도에 닿을지 — 숫자로 가볍게.

리셋 2026-06-01 플랜 한도 {u.quota}건
이번 달 발행
{u.month_publish}/ {u.quota}건 · {pct}%
5월 1일 오늘 (5월 8일) 5월 31일
{pct >= 40 && (
예상 소진 5월 24일경 — 현재 페이스로는 한도 도달 전 1주일이 빠듯합니다.
발행 시간을 1회로 줄이거나 PRO 플랜(무제한)을 검토해보세요.
)}

최근 30일 발행 추세

{days.map((d,i)=>(
))}
30일 전15일 전오늘
평균 4.7건/일 · 최고 {max}건 · 최저 {Math.min(...days)}건
자동 발행 성공률
98.2%
최근 30일 · 실패 2건
남은 발행
{u.quota - u.month_publish}건
오늘 페이스로 약 33일치
초과 위험도
중간
현재 페이스 기준

사용량 줄이기 / 늘리기

발행 시간을 2회 → 1회로 줄이기 예상 절감 -30건/월 · 한도 안에서 안정 운영
PRO 플랜으로 업그레이드 (한도 제거) 현재 142건 → PRO에서는 한도 없음 · 월 ₩29,000
); }; /* ===== NEW · 환경설정 ===== */ function ToggleRow({ label, sub, on, onChange, right }){ return (
{label} {sub}
{right ||
); } window.SaasSettings = function({ go }){ const [pubAlert, setPubAlert] = u2(true); const [emailAlert, setEmailAlert] = u2(false); const [slackAlert, setSlackAlert] = u2(false); const [weekly, setWeekly] = u2(true); const [time, setTime] = u2('09:00'); const [tz, setTz] = u2('Asia/Seoul (KST · UTC+9)'); const [defCat, setDefCat] = u2('전자'); const [defTone, setDefTone] = u2('가성비'); const [defTmpl, setDefTmpl] = u2('T01_A'); const [defChar, setDefChar] = u2('C07'); return (
관리

환경설정

발행 습관·알림·기본값을 조정합니다. 계정·보안은 하단에서.

이메일 {SAAS_USER2.email}
{/* 알림 */}
알림
발행 결과·실패·쿼터 임박 등 어떤 이벤트를 받을지 골라주세요.
setPubAlert(!pubAlert)}/> setEmailAlert(!emailAlert)}/> setSlackAlert(!slackAlert)}/> setWeekly(!weekly)}/>
{/* 발행 시간대 */}
발행 시간대
자동 발행이 시작되는 시각과 기준 타임존입니다.
setTime(e.target.value)}> }/> setTz(e.target.value)} style={{minWidth:200}}> }/>
{/* 기본값 */}
발행 기본값
발행 설정에서 따로 바꾸지 않으면 이 값으로 발행됩니다.
setDefCat(e.target.value)}> {['전자','생활','뷰티','패션','건강','금융'].map(c=>)} }/> setDefTone(e.target.value)}> {['가성비','프리미엄','입문자','전문가','트렌드'].map(c=>)} }/> setDefTmpl(e.target.value)}> {['T01_A','T02_A','T03_A','T04_A','T05_A','T06_A'].map(c=>)} }/> setDefChar(e.target.value)}> {['C07','C12','C03','C09','C15','C18'].map(c=>)} }/>
{/* 계정·보안 */}
계정·보안
비밀번호·로그인 세션·연결된 외부 계정.
변경하기}/> 세션 보기}/> 관리}/> 해지 신청}/>
); };