feat(site): rework 19 marketing showcases for composition diversity
Some checks are pending
ci / build (push) Waiting to run
Some checks are pending
ci / build (push) Waiting to run
Measured convergence before: split hero 13/19, top-bar nav 19/19, one-line notice footer 14/19, body Pretendard 17/21, 10 similarity pairs above 0.78. Each showcase got a pre-assigned hero family, nav form, footer form, type pair, background, accent hue, radius, motion grammar and material from outputs/rework-2026-10-06/plan.md; direction cards and the chosen reason are recorded in every design.md. After: 0 similarity warnings, 19 distinct display faces, 7 hero families, 5 nav forms, 5 footer forms, no scroll reveals, 5 showcases with SVG filter materials. Example contact values replace bracket placeholders under the existing fictional-brand notices. Thumbnails, OG images, card copy and three e2e assertions updated; dead CSS in dure-enrollment and hannam-jari removed; similarity.mjs learns the new font families.
This commit is contained in:
parent
88c11682b1
commit
8e3cdb0d3b
296 changed files with 19131 additions and 17538 deletions
|
|
@ -3,372 +3,248 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<title>청온 케어 · 프리미엄 주거·오피스 위생 케어 안내</title>
|
||||
<title>청온 케어 입주청소 견적</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="위생 케어 절차, 예상 견적, 운영 정보의 표시 방식을 소개합니다. 가격과 접수 정보는 예시이며 실제 신청은 진행되지 않습니다."
|
||||
content="공간 유형과 평형, 추가 옵션을 고르면 항목별 단가와 합계가 바로 나옵니다. 청소가 끝나면 32개 검수 항목을 현장 팀장과 함께 확인하고 서명하는 가상 입주청소 서비스입니다."
|
||||
/>
|
||||
<meta property="og:title" content="청온 케어 · 프리미엄 위생 케어" />
|
||||
<meta property="og:description" content="공간의 숨결을 되돌리는 6단계 프로토콜과 투명한 정찰제 견적." />
|
||||
<meta property="og:title" content="청온 케어 입주청소 견적" />
|
||||
<meta property="og:description" content="평당 단가로 바로 계산하는 견적, 6단계 작업 절차, 32개 항목 마감 검수." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta name="theme-color" content="#f8faf9" />
|
||||
<meta property="og:image" content="https://designpaca.chanpaca.net/work/cheongon-care/assets/steam-qc.webp" />
|
||||
<meta property="og:image:alt" content="청온 케어 현장에서 쓰는 스팀 청소기와 세척 노즐, 극세사 천, 세제 샘플" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="theme-color" content="#eef3f6" />
|
||||
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
|
||||
href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap"
|
||||
/>
|
||||
<link rel="stylesheet" href="./styles/fonts.css?v=20260912all" />
|
||||
<link rel="stylesheet" href="./styles/main.css?v=20260912all" />
|
||||
<link rel="stylesheet" href="./styles/tokens.css?v=20261006" />
|
||||
<link rel="stylesheet" href="./styles/main.css?v=20261006" />
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%230D9488'/%3E%3Cpath d='M9 16.5l5 5 9-10' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%23156a75'/%3E%3Cpath d='M9 16.5l5 5 9-10' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body data-view="client">
|
||||
<a class="skip-link" href="#mainContent">본문으로 건너뛰기</a>
|
||||
|
||||
<!-- 최상단 헤더 (.site-head SSOT) -->
|
||||
<!-- 공통 셸: 내비 없음. 상호와 행동 하나만 둔다 -->
|
||||
<header class="site-head">
|
||||
<div class="wrap head-inner">
|
||||
<a class="wordmark" href="#" id="brandLogo">
|
||||
<span class="wordmark-badge">청</span>
|
||||
청온 케어
|
||||
</a>
|
||||
|
||||
<nav class="nav" aria-label="메인 메뉴">
|
||||
<a href="#services">케어 솔루션</a>
|
||||
<a href="#calculator">정찰제 견적</a>
|
||||
<a href="./protocol/index.html" style="color: var(--accent); font-weight: 600;">6단계 프로토콜 (상세)</a>
|
||||
<a href="#equipment">전문 장비</a>
|
||||
</nav>
|
||||
|
||||
<div class="head-actions">
|
||||
<div class="mode-toggle" role="group" aria-label="뷰 모드 전환">
|
||||
<button type="button" class="mode-btn is-active" id="btnModeClient">
|
||||
고객 소개 뷰
|
||||
</button>
|
||||
<button type="button" class="mode-btn" id="btnModeAdmin" title="단축키: Alt + A">
|
||||
<span class="badge-dot" aria-hidden="true"></span>
|
||||
운영 현황
|
||||
</button>
|
||||
</div>
|
||||
<a href="#calculator" class="btn client-only-btn">
|
||||
간편 견적
|
||||
</a>
|
||||
</div>
|
||||
<a class="wordmark" href="./index.html" id="brandLogo">청온 케어</a>
|
||||
<a class="head-action" href="#request">견적 요청</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="mainContent">
|
||||
<!-- ===================================================================
|
||||
1. 고객 소개 및 간편 신청 뷰 (Client View)
|
||||
=================================================================== -->
|
||||
<div class="client-view">
|
||||
<!-- 히어로 섹션 -->
|
||||
<section class="hero-section" aria-labelledby="heroHeading">
|
||||
<div class="wrap hero-grid">
|
||||
<div class="hero-content">
|
||||
<div class="eyebrow">
|
||||
<span>현장 검수 절차 예시</span>
|
||||
</div>
|
||||
<h1 id="heroHeading" class="hero-title">
|
||||
보이지 않는 오염까지,<br />
|
||||
<em>공간을 새롭게</em> 돌봅니다
|
||||
</h1>
|
||||
<p class="hero-desc">
|
||||
공간 유형과 선택 항목을 바탕으로 케어 범위와 예상 금액을 살펴볼 수 있습니다.
|
||||
</p>
|
||||
<div class="hero-ctas">
|
||||
<a href="#calculator" class="btn-primary">
|
||||
항목별 예상 견적 보기
|
||||
<span class="btn-icon-circle" aria-hidden="true">↗</span>
|
||||
</a>
|
||||
<div class="hero-trust">
|
||||
<span>선택 항목별 예상 금액을 확인하세요</span>
|
||||
<!-- 첫 화면: 견적 계산기가 주인. 표제는 작게, 리드는 사실 목록 -->
|
||||
<section class="quote" id="calculator" aria-labelledby="heroHeading">
|
||||
<div class="wrap quote-grid">
|
||||
<div class="quote-intro">
|
||||
<h1 id="heroHeading" class="quote-title">입주·이사 청소 견적, 평형과 옵션을 고르면 바로 나옵니다</h1>
|
||||
<dl class="facts">
|
||||
<div class="fact">
|
||||
<dt>기본 단가</dt>
|
||||
<dd>평당 9,500원부터</dd>
|
||||
</div>
|
||||
</div>
|
||||
<p class="demo-notice" role="note">안내: 이 페이지의 서비스·가격·운영 현황은 예시입니다. 입력 정보는 저장·전송되지 않으며 실제 견적이나 신청으로 이어지지 않습니다.</p>
|
||||
<div class="fact">
|
||||
<dt>범위</dt>
|
||||
<dd>주거 입주와 이사, 사무실 정기, 준공 청소</dd>
|
||||
</div>
|
||||
<div class="fact">
|
||||
<dt>검수</dt>
|
||||
<dd>32개 항목을 현장 팀장과 함께 확인하고 서명</dd>
|
||||
</div>
|
||||
<div class="fact">
|
||||
<dt>추가 옵션</dt>
|
||||
<dd>스팀, 피톤치드, 에어컨 분해, 유리창 발수 4종</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="hero-visual">
|
||||
<figure class="hero-frame">
|
||||
<img
|
||||
src="./assets/clean-hero.webp"
|
||||
alt="정돈된 주거 공간의 거실 전경"
|
||||
width="1200"
|
||||
height="900"
|
||||
loading="eager"
|
||||
/>
|
||||
<figcaption>주거 공간 케어 예시 · 현장에서는 32개 검수 항목을 확인하는 흐름을 표시합니다.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 실시간 정찰제 견적 계산기 -->
|
||||
<section class="calc-section" id="calculator" aria-labelledby="calcHeading">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<p class="eyebrow">견적 작업표</p>
|
||||
<h2 id="calcHeading" class="section-title">항목별 예상 견적</h2>
|
||||
<p class="section-sub">공간 면적과 선택 항목을 기준으로 예상 금액의 구성 방식을 확인합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="calc-grid">
|
||||
<div class="calc-card">
|
||||
<form id="quoteForm" onsubmit="return false;">
|
||||
<!-- 공간 유형 -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" id="spaceTypeLabel">공간 유형 선택</label>
|
||||
<div class="type-selector" role="radiogroup" aria-labelledby="spaceTypeLabel">
|
||||
<button type="button" class="type-btn is-active" data-type="apt" data-base="11000">
|
||||
주거 입주/이사
|
||||
</button>
|
||||
<button type="button" class="type-btn" data-type="office" data-base="9500">
|
||||
오피스 정기 케어
|
||||
</button>
|
||||
<button type="button" class="type-btn" data-type="premium" data-base="14500">
|
||||
하이엔드 준공 청소
|
||||
</button>
|
||||
</div>
|
||||
<div class="quote-tool">
|
||||
<form id="quoteForm" class="quote-form" onsubmit="return false;">
|
||||
<fieldset class="form-group">
|
||||
<legend class="form-label">공간 유형</legend>
|
||||
<div class="type-selector" role="radiogroup" aria-label="공간 유형">
|
||||
<button type="button" class="type-btn is-active" data-type="apt" data-base="11000" aria-pressed="true">
|
||||
주거 입주/이사
|
||||
</button>
|
||||
<button type="button" class="type-btn" data-type="office" data-base="9500" aria-pressed="false">
|
||||
사무실 정기 청소
|
||||
</button>
|
||||
<button type="button" class="type-btn" data-type="premium" data-base="14500" aria-pressed="false">
|
||||
준공 청소
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- 평수 슬라이더 -->
|
||||
<div class="form-group">
|
||||
<div class="slider-header">
|
||||
<label class="form-label" for="pyeongSlider">공간 공급면적 (평형)</label>
|
||||
<span class="slider-val" id="pyeongValue">32 평 (약 105㎡)</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
id="pyeongSlider"
|
||||
name="spaceSize"
|
||||
class="range-input"
|
||||
min="12"
|
||||
max="75"
|
||||
value="32"
|
||||
step="1"
|
||||
/>
|
||||
<div class="form-group">
|
||||
<div class="slider-header">
|
||||
<label class="form-label" for="pyeongSlider">공급면적</label>
|
||||
<output class="slider-val" id="pyeongValue" for="pyeongSlider">32평 (약 105㎡)</output>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
id="pyeongSlider"
|
||||
name="spaceSize"
|
||||
class="range-input"
|
||||
min="12"
|
||||
max="75"
|
||||
value="32"
|
||||
step="1"
|
||||
/>
|
||||
<div class="slider-scale" aria-hidden="true"><span>12평</span><span>75평</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 특수 케어 옵션 -->
|
||||
<div class="form-group">
|
||||
<span class="form-label">정밀 특수 옵션</span>
|
||||
<div class="addon-grid">
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="steam" data-price="45000" checked />
|
||||
<span>고온 스팀 작업 기록 (+45,000원)</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="phytoncide" data-price="35000" checked />
|
||||
<span>향·마감 작업 기록 (+35,000원)</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="aircon" data-price="80000" />
|
||||
<span>시스템 에어컨 분해 (+80,000원)</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="glass" data-price="50000" />
|
||||
<span>외부 유리창 특수 발수 (+50,000원)</span>
|
||||
</label>
|
||||
</div>
|
||||
<fieldset class="form-group">
|
||||
<legend class="form-label">추가 옵션</legend>
|
||||
<div class="addon-grid">
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="steam" data-price="45000" checked />
|
||||
<span class="addon-name">고온 스팀 청소</span>
|
||||
<span class="addon-price">+45,000원</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="phytoncide" data-price="35000" checked />
|
||||
<span class="addon-name">피톤치드 마감</span>
|
||||
<span class="addon-price">+35,000원</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="aircon" data-price="80000" />
|
||||
<span class="addon-name">시스템 에어컨 분해</span>
|
||||
<span class="addon-price">+80,000원</span>
|
||||
</label>
|
||||
<label class="addon-label">
|
||||
<input type="checkbox" name="addon" value="glass" data-price="50000" />
|
||||
<span class="addon-name">외부 유리창 발수 코팅</span>
|
||||
<span class="addon-price">+50,000원</span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<!-- 예약 정보 입력 -->
|
||||
<div class="form-group" style="margin-top: 1.5rem;">
|
||||
<span class="form-label">신청자 정보</span>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 0.75rem;">
|
||||
<label class="sr-only" for="clientName">신청자 성함</label>
|
||||
<input
|
||||
type="text"
|
||||
id="clientName"
|
||||
name="clientName"
|
||||
autocomplete="name"
|
||||
placeholder="성함 / 고객명"
|
||||
style="width: 100%; min-width: 0; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: var(--step--1);"
|
||||
required
|
||||
/>
|
||||
<label class="sr-only" for="clientPhone">신청자 연락처</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="clientPhone"
|
||||
name="clientPhone"
|
||||
autocomplete="tel"
|
||||
placeholder="연락처 (010-0000-0000)"
|
||||
style="width: 100%; min-width: 0; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: var(--step--1);"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<label class="sr-only" for="clientAddress">케어 현장 주소</label>
|
||||
<input
|
||||
type="text"
|
||||
id="clientAddress"
|
||||
name="clientAddress"
|
||||
autocomplete="off"
|
||||
placeholder="케어 현장 주소 (예: 서울시 마포구 공덕동 120)"
|
||||
style="width: 100%; min-width: 0; margin-top: 0.5rem; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: var(--step--1);"
|
||||
required
|
||||
/>
|
||||
<div class="quote-summary" aria-live="polite" aria-atomic="true">
|
||||
<h2 class="summary-title">예상 견적</h2>
|
||||
<dl class="summary-list">
|
||||
<div class="summary-row">
|
||||
<dt>공간</dt>
|
||||
<dd id="sumSpaceType">주거 입주/이사</dd>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 요약 및 접수 CTA -->
|
||||
<div class="calc-summary">
|
||||
<h3 class="summary-title">예상 견적 명세</h3>
|
||||
<div class="summary-row">
|
||||
<span>선택 공간</span>
|
||||
<span id="sumSpaceType" class="mono">주거 입주/이사</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span>면적 기준</span>
|
||||
<span id="sumPyeong" class="mono">32평 (평당 11,000원)</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span>기본 케어비</span>
|
||||
<span id="sumBasePrice" class="mono">352,000원</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span>정밀 옵션 합계</span>
|
||||
<span id="sumAddonPrice" class="mono">80,000원</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<dt>면적</dt>
|
||||
<dd id="sumPyeong">32평 (평당 11,000원)</dd>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<dt>기본 청소비</dt>
|
||||
<dd id="sumBasePrice">352,000원</dd>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<dt>추가 옵션</dt>
|
||||
<dd id="sumAddonPrice">80,000원</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="summary-total">
|
||||
<span>총 예상 견적</span>
|
||||
<span class="total-amount" id="sumTotal">432,000원</span>
|
||||
<span class="summary-total-label">합계</span>
|
||||
<strong class="total-amount" id="sumTotal">432,000원</strong>
|
||||
</div>
|
||||
|
||||
<button type="button" class="calc-submit" id="btnSubmitQuote">
|
||||
예상 견적 보기
|
||||
</button>
|
||||
<p style="font-size: 12px; color: var(--ink-muted); margin-top: 10px; text-align: center;">
|
||||
선택 항목에 따른 예상 금액을 확인할 수 있습니다. 실제 견적·신청은 진행되지 않습니다.
|
||||
</p>
|
||||
<a href="#request" class="btn-primary summary-cta">이 금액으로 견적 요청</a>
|
||||
<p class="summary-note">예시 금액입니다. 실제 견적과 신청은 진행되지 않습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6단계 위생 프로토콜 -->
|
||||
<section class="protocol-section" id="protocol" aria-labelledby="protoHeading">
|
||||
<div class="wrap">
|
||||
<div class="section-head" style="display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 12px;">
|
||||
<div>
|
||||
<h2 id="protoHeading" class="section-title">6단계 현장 검수 절차 예시</h2>
|
||||
<p class="section-sub">작업 순서와 확인 항목을 기록하는 방식의 예시입니다. 결과나 성능을 보증하지 않습니다.</p>
|
||||
</div>
|
||||
<a href="./protocol/index.html" class="action-btn" style="text-decoration: none; padding: 10px 20px; font-size: 14px; background: var(--surface-card); color: var(--accent); border: 1px solid var(--accent);">
|
||||
검수 절차 예시 보기 →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="protocol-grid">
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 01</div>
|
||||
<h3>건식 초미세 집진</h3>
|
||||
<p>벽면, 천장 몰딩, 바닥의 시공 잔여물을 확인하고 흡진 작업 여부를 기록합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 02</div>
|
||||
<h3>스팀 장비 설정 확인</h3>
|
||||
<p>배수구, 욕실 타일 틈새, 주방 후드처럼 확인이 필요한 면과 장비 설정을 작업표에 기록합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 03</div>
|
||||
<h3>표면별 세정 확인</h3>
|
||||
<p>표면 재질과 사용 제품 정보를 작업표에 기록하고, 적용 전후 상태를 함께 확인합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 04</div>
|
||||
<h3>서랍·후드 전면 탈거 세척</h3>
|
||||
<p>필요한 분리 작업의 범위와 접근 가능한 안쪽 면을 확인 항목으로 남깁니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 05</div>
|
||||
<h3>환기와 마감 확인</h3>
|
||||
<p>환기와 마감 상태를 확인하고, 사용한 향·마감 제품이 있다면 작업표에 표시합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="protocol-card">
|
||||
<div class="protocol-num">STEP 06</div>
|
||||
<h3>32개 항목 마스터 검수</h3>
|
||||
<p>현장 담당자와 의뢰자가 검수 항목을 함께 확인하는 흐름을 예시로 표시합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 전문 장비 & Before/After -->
|
||||
<section class="equipment-section" id="equipment" aria-labelledby="equipHeading">
|
||||
<!-- 6단계 절차 -->
|
||||
<section class="steps" id="protocol" aria-labelledby="stepsHeading">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<h2 id="equipHeading" class="section-title">작업 장비와 검수 기록</h2>
|
||||
<p class="section-sub">현장에서 확인할 장비·필터·제품·마감 항목을 작업표에 표시하는 예시입니다.</p>
|
||||
<h2 id="stepsHeading" class="section-title">6단계로 작업하고, 단계마다 쓴 장비와 제품을 작업표에 적습니다</h2>
|
||||
<a href="./protocol/index.html" class="text-link">절차 상세 보기</a>
|
||||
</div>
|
||||
|
||||
<div class="equip-grid">
|
||||
<div class="equip-specs">
|
||||
<div class="spec-item">
|
||||
<span class="spec-key">장비 기록</span>
|
||||
<span class="spec-val">사용 장비와 설정값을 작업표에 표시</span>
|
||||
</div>
|
||||
<div class="spec-item">
|
||||
<span class="spec-key">필터 확인</span>
|
||||
<span class="spec-val">필터 종류와 교체 상태를 현장에서 확인</span>
|
||||
</div>
|
||||
<div class="spec-item">
|
||||
<span class="spec-key">사용 제품</span>
|
||||
<span class="spec-val">제품명과 적용 표면을 작업표에 기록</span>
|
||||
</div>
|
||||
<div class="spec-item">
|
||||
<span class="spec-key">마감 확인</span>
|
||||
<span class="spec-val">환기·표면 상태를 검수 항목으로 확인</span>
|
||||
</div>
|
||||
</div>
|
||||
<ol class="step-list">
|
||||
<li class="step">
|
||||
<h3>공사 먼지 흡진</h3>
|
||||
<p>벽면, 천장 몰딩, 바닥의 시공 잔여물을 확인하고 흡진 작업 여부를 기록합니다.</p>
|
||||
</li>
|
||||
<li class="step">
|
||||
<h3>스팀 장비 설정 확인</h3>
|
||||
<p>배수구, 욕실 타일 줄눈, 주방 후드를 스팀으로 청소하고 장비 온도 설정을 작업표에 적습니다.</p>
|
||||
</li>
|
||||
<li class="step">
|
||||
<h3>재질에 맞는 세제 사용</h3>
|
||||
<p>대리석, 원목, 스테인리스 등 재질에 맞는 세제를 쓰고 사용한 제품을 작업표에 적습니다.</p>
|
||||
</li>
|
||||
<li class="step">
|
||||
<h3>서랍과 후드 분리 세척</h3>
|
||||
<p>서랍과 후드 필터를 떼어 내 안쪽까지 닦고, 분리한 부위를 작업표에 표시합니다.</p>
|
||||
</li>
|
||||
<li class="step">
|
||||
<h3>환기와 마감 확인</h3>
|
||||
<p>환기와 마감 상태를 확인하고, 사용한 향이나 마감 제품이 있으면 작업표에 표시합니다.</p>
|
||||
</li>
|
||||
<li class="step">
|
||||
<h3>32개 항목 최종 검수</h3>
|
||||
<p>현장 팀장과 고객님이 32개 검수 항목을 작업표로 함께 확인하고 서명합니다.</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="ba-container">
|
||||
<img
|
||||
src="./assets/steam-qc.webp"
|
||||
alt="청온 케어 마스터 위생 장비와 정밀 세척 노즐"
|
||||
width="800"
|
||||
height="600"
|
||||
loading="lazy"
|
||||
/>
|
||||
<span class="ba-badge before">작업 장비 예시</span>
|
||||
<span class="ba-badge after">검수 항목 확인</span>
|
||||
</div>
|
||||
<!-- 장비와 기록 -->
|
||||
<section class="gear" id="equipment" aria-labelledby="gearHeading">
|
||||
<div class="wrap gear-grid">
|
||||
<figure class="gear-cutout">
|
||||
<img
|
||||
src="./assets/steam-qc.webp"
|
||||
alt="청온 케어 현장에서 쓰는 스팀 청소기와 세척 노즐, 극세사 천, 세제 샘플"
|
||||
width="800"
|
||||
height="600"
|
||||
loading="lazy"
|
||||
/>
|
||||
<figcaption>스팀 청소기, 극세사 천, 세제 샘플. 현장에서 쓰는 장비와 제품입니다.</figcaption>
|
||||
</figure>
|
||||
<div class="gear-text">
|
||||
<h2 id="gearHeading" class="section-title">장비 설정값과 사용 제품은 현장에서 작업표에 적습니다</h2>
|
||||
<dl class="record-list">
|
||||
<div class="record">
|
||||
<dt>장비</dt>
|
||||
<dd>사용 장비와 설정값을 작업표에 표시합니다.</dd>
|
||||
</div>
|
||||
<div class="record">
|
||||
<dt>필터</dt>
|
||||
<dd>필터 종류와 교체 상태를 현장에서 확인합니다.</dd>
|
||||
</div>
|
||||
<div class="record">
|
||||
<dt>제품</dt>
|
||||
<dd>제품명과 적용 표면을 작업표에 기록합니다.</dd>
|
||||
</div>
|
||||
<div class="record">
|
||||
<dt>마감</dt>
|
||||
<dd>환기와 표면 상태를 검수 항목으로 확인합니다.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- ===================================================================
|
||||
2. 운영 현황 보기
|
||||
=================================================================== -->
|
||||
<!-- 운영 현황 보기 (예시 화면) -->
|
||||
<section class="admin-view wrap" aria-label="청온 케어 운영 현황">
|
||||
<div class="admin-header">
|
||||
<div>
|
||||
<div class="eyebrow" style="margin-bottom: 4px;">운영 현황</div>
|
||||
<h2 style="font-size: var(--step-2); font-weight: 800;">오늘의 케어 현황</h2>
|
||||
<p class="demo-notice" role="note">아래 접수·배차 정보는 운영 화면 예시입니다. 실제 고객 정보나 접수 내역이 아닙니다.</p>
|
||||
<h2 class="section-title">오늘 작업 현황</h2>
|
||||
<p class="demo-notice" role="note">아래 접수와 배차 정보는 운영 화면 예시입니다. 실제 고객 정보나 접수 내역이 아닙니다.</p>
|
||||
</div>
|
||||
<button type="button" class="btn-primary" id="btnOpenQcModal">
|
||||
32개 검수 항목 보기
|
||||
</button>
|
||||
<button type="button" class="btn-primary" id="btnOpenQcModal">32개 검수 항목 보기</button>
|
||||
</div>
|
||||
|
||||
<!-- KPI 통계 카드 -->
|
||||
<div class="admin-kpis">
|
||||
<div class="kpi-card">
|
||||
<div class="kpi-label">오늘 신규 접수</div>
|
||||
|
|
@ -379,34 +255,33 @@
|
|||
<div class="kpi-val">4개 조</div>
|
||||
</div>
|
||||
<div class="kpi-card">
|
||||
<div class="kpi-label">검수 대기 / 완료</div>
|
||||
<div class="kpi-label">검수 대기</div>
|
||||
<div class="kpi-val">2건</div>
|
||||
</div>
|
||||
<div class="kpi-card">
|
||||
<div class="kpi-label">오늘 견적 총액</div>
|
||||
<div class="kpi-val mono" id="kpiTotalRevenue">2,480,000원</div>
|
||||
<div class="kpi-val" id="kpiTotalRevenue">2,480,000원</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 실시간 접수 및 배차 원장 테이블 -->
|
||||
<div class="admin-table-card">
|
||||
<div class="table-header">
|
||||
<span class="table-title">접수·배차 현황</span>
|
||||
<div class="table-filter-tabs">
|
||||
<button class="filter-tab is-active" data-filter="all">전체</button>
|
||||
<button class="filter-tab" data-filter="new">신규접수</button>
|
||||
<button class="filter-tab" data-filter="progress">진행중</button>
|
||||
<button class="filter-tab" data-filter="done">완료</button>
|
||||
<span class="table-title">접수와 배차 현황</span>
|
||||
<div class="table-filter-tabs" role="group" aria-label="상태 필터">
|
||||
<button type="button" class="filter-tab is-active" data-filter="all">전체</button>
|
||||
<button type="button" class="filter-tab" data-filter="new">신규접수</button>
|
||||
<button type="button" class="filter-tab" data-filter="progress">진행중</button>
|
||||
<button type="button" class="filter-tab" data-filter="done">완료</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="overflow-x: auto;">
|
||||
<div class="table-scroll">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">접수번호</th>
|
||||
<th scope="col">고객명 / 연락처</th>
|
||||
<th scope="col">공간 / 면적</th>
|
||||
<th scope="col">고객명</th>
|
||||
<th scope="col">공간</th>
|
||||
<th scope="col">현장 주소</th>
|
||||
<th scope="col">견적액</th>
|
||||
<th scope="col">배정 팀장</th>
|
||||
|
|
@ -416,108 +291,157 @@
|
|||
</thead>
|
||||
<tbody id="adminTableBody">
|
||||
<tr>
|
||||
<td class="mono">#CO-2026-0819</td>
|
||||
<td><strong>이서연</strong><br /><span style="color:var(--ink-muted);font-size:11px;">010-4821-9930</span></td>
|
||||
<td class="num">#CO-2026-0819</td>
|
||||
<td><strong>이서연</strong><br /><span class="cell-sub">010-4821-9930</span></td>
|
||||
<td>주거 입주 (32평)</td>
|
||||
<td>성동구 성수동 아크로포레스트</td>
|
||||
<td class="mono" style="font-weight:700;">432,000원</td>
|
||||
<td>김정온 마스터</td>
|
||||
<td class="num cell-strong">432,000원</td>
|
||||
<td>김정온 팀장 (3팀)</td>
|
||||
<td><span class="status-pill new">신규 접수</span></td>
|
||||
<td><button class="action-btn" onclick="alert('배차 상태를 확인했습니다. 이 화면의 접수 정보는 예시이며 실제 알림은 전송되지 않습니다.');">배차 상태 보기</button></td>
|
||||
<td><button type="button" class="action-btn" onclick="alert('배차 상태를 확인했습니다. 이 화면의 접수 정보는 예시이며 실제 알림은 전송되지 않습니다.');">배차 상태 보기</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">#CO-2026-0818</td>
|
||||
<td><strong>박도현</strong><br /><span style="color:var(--ink-muted);font-size:11px;">010-9120-3341</span></td>
|
||||
<td>오피스 정기 (45평)</td>
|
||||
<td class="num">#CO-2026-0818</td>
|
||||
<td><strong>박도현</strong><br /><span class="cell-sub">010-9120-3341</span></td>
|
||||
<td>사무실 정기 (45평)</td>
|
||||
<td>강남구 테헤란로 142 위워크</td>
|
||||
<td class="mono" style="font-weight:700;">520,000원</td>
|
||||
<td class="num cell-strong">520,000원</td>
|
||||
<td>박준호 팀장 (2팀)</td>
|
||||
<td><span class="status-pill progress">스팀 케어 중</span></td>
|
||||
<td><button class="action-btn" onclick="document.getElementById('qcModal').showModal();">검수 항목 보기</button></td>
|
||||
<td><span class="status-pill progress">작업 중</span></td>
|
||||
<td><button type="button" class="action-btn" onclick="document.getElementById('qcModal').showModal();">검수 항목 보기</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">#CO-2026-0817</td>
|
||||
<td><strong>한지민</strong><br /><span style="color:var(--ink-muted);font-size:11px;">010-7712-4091</span></td>
|
||||
<td>하이엔드 준공 (58평)</td>
|
||||
<td class="num">#CO-2026-0817</td>
|
||||
<td><strong>한지민</strong><br /><span class="cell-sub">010-7712-4091</span></td>
|
||||
<td>준공 청소 (58평)</td>
|
||||
<td>용산구 한남동 나인원한남</td>
|
||||
<td class="mono" style="font-weight:700;">841,000원</td>
|
||||
<td>최수진 닥터 (1팀)</td>
|
||||
<td class="num cell-strong">841,000원</td>
|
||||
<td>최수진 팀장 (1팀)</td>
|
||||
<td><span class="status-pill done">검수 승인 완료</span></td>
|
||||
<td><button class="action-btn" onclick="alert('검수 리포트 내용을 확인했습니다. 실제 발행은 진행되지 않습니다.');">리포트 보기</button></td>
|
||||
<td><button type="button" class="action-btn" onclick="alert('검수 리포트 내용을 확인했습니다. 실제 발행은 진행되지 않습니다.');">리포트 보기</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 화면 전환: 고객 화면과 운영 화면 예시 -->
|
||||
<div class="wrap view-switch">
|
||||
<span class="view-switch-label" id="viewSwitchLabel">화면</span>
|
||||
<div class="mode-toggle" role="group" aria-labelledby="viewSwitchLabel">
|
||||
<button type="button" class="mode-btn is-active" id="btnModeClient" aria-pressed="true">고객 화면</button>
|
||||
<button type="button" class="mode-btn" id="btnModeAdmin" aria-pressed="false" title="단축키: Alt + A">운영 화면 예시</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 32개 항목 QC 검수 모달 다이얼로그 -->
|
||||
<!-- 32개 항목 검수표 -->
|
||||
<dialog id="qcModal" class="qc-dialog" aria-labelledby="qcTitle">
|
||||
<div class="qc-head">
|
||||
<h3 id="qcTitle" style="font-size: var(--step-1); font-weight: 700;">32개 정밀 위생 검수 체크리스트</h3>
|
||||
<button type="button" onclick="document.getElementById('qcModal').close();" aria-label="닫기" style="font-size: 18px; font-weight: 700;">✕</button>
|
||||
<h3 id="qcTitle" class="qc-title">32개 항목 검수표</h3>
|
||||
<button type="button" class="icon-btn" onclick="document.getElementById('qcModal').close();" aria-label="닫기">✕</button>
|
||||
</div>
|
||||
<ul class="qc-list">
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>01. 천장 몰딩 및 전등갓 상단 분진 흡진</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>02. 창틀 상하좌우 틈새 시멘트 가루 및 찌든때 제거</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>03. 싱크대 하부 걸레받이 전면 탈거 및 분진 집진</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>04. 가스레인지/인덕션 상판 및 후드 필터 기름때 고온 스팀 분해</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>05. 욕실 벽타일 메지 및 배수구 트랩 스팀 작업 확인</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>06. 수납장 모든 서랍 완전 탈거 후 레일 틈새 분진 청소</span></li>
|
||||
<li class="qc-item"><input type="checkbox" checked /> <span>07. 베란다 및 다용도실 바닥 타일 세정 작업 확인</span></li>
|
||||
<li class="qc-item"><input type="checkbox" /> <span>08. 전 실 환기와 마감 상태 확인</span></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>01. 천장 몰딩 및 전등갓 상단 분진 흡진</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>02. 창틀 상하좌우 틈새 시멘트 가루 및 찌든때 제거</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>03. 싱크대 하부 걸레받이 전면 탈거 및 분진 집진</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>04. 가스레인지/인덕션 상판 및 후드 필터 기름때 고온 스팀 분해</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>05. 욕실 벽타일 줄눈과 배수구 트랩 스팀 청소</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>06. 수납장 모든 서랍 완전 탈거 후 레일 틈새 분진 청소</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" checked /> <span>07. 베란다와 다용도실 바닥 타일 청소</span></label></li>
|
||||
<li class="qc-item"><label><input type="checkbox" /> <span>08. 전 실 환기와 마감 상태 확인</span></label></li>
|
||||
</ul>
|
||||
<div style="display: flex; justify-content: flex-end; gap: 8px;">
|
||||
<p class="qc-note">32개 항목 가운데 8개를 예시로 보입니다.</p>
|
||||
<div class="qc-actions">
|
||||
<button type="button" class="action-btn" onclick="document.getElementById('qcModal').close();">닫기</button>
|
||||
<button type="button" class="btn-primary" style="padding: 6px 14px; font-size: 13px;" onclick="alert('검수 항목을 확인했습니다. 이 화면에서 실제 승인 처리는 진행되지 않습니다.'); document.getElementById('qcModal').close();">검수 항목 확인</button>
|
||||
<button type="button" class="btn-primary btn-small" onclick="alert('검수 항목을 확인했습니다. 이 화면에서 실제 승인 처리는 진행되지 않습니다.'); document.getElementById('qcModal').close();">검수 항목 확인</button>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<!-- 푸터 (.site-foot SSOT) -->
|
||||
<!-- 전화 (모바일 하단 바) — 가상 브랜드라 번호는 예시다. 실제로 연결되지 않는다 -->
|
||||
<dialog id="callDialog" class="call-dialog" aria-labelledby="callTitle">
|
||||
<h3 id="callTitle" class="qc-title">전화 문의</h3>
|
||||
<p class="call-number">02-000-4172</p>
|
||||
<p class="call-note">예시 번호라 실제로 연결되지 않습니다. 견적 요청 폼으로 흐름을 확인할 수 있습니다.</p>
|
||||
<div class="qc-actions">
|
||||
<button type="button" class="action-btn" onclick="document.getElementById('callDialog').close();">닫기</button>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<!-- 푸터: 다음 행동 하나(견적 요청)가 푸터의 대부분이다 -->
|
||||
<footer class="site-foot">
|
||||
<div class="wrap foot-inner">
|
||||
<p>청온 케어 · 위생 케어 안내</p>
|
||||
<p class="muted">이 페이지의 가격·접수 정보는 예시이며 입력 정보는 저장·전송되지 않습니다.</p>
|
||||
<section class="wrap request" id="request" aria-labelledby="requestHeading">
|
||||
<div class="request-head">
|
||||
<h2 id="requestHeading" class="request-title">견적을 요청합니다</h2>
|
||||
<p class="request-lead">위에서 고른 조건으로 <output class="request-total" id="requestTotal" for="quoteForm">432,000원</output>이 계산됐습니다. 연락처를 남기면 현장 팀장이 일정을 잡습니다.</p>
|
||||
</div>
|
||||
<form id="requestForm" class="request-form" onsubmit="return false;">
|
||||
<div class="field">
|
||||
<label class="form-label" for="clientName">성함</label>
|
||||
<input type="text" id="clientName" name="clientName" autocomplete="name" class="text-input" required />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="form-label" for="clientPhone">연락처</label>
|
||||
<input type="tel" id="clientPhone" name="clientPhone" autocomplete="tel" class="text-input" placeholder="010-0000-0000" required />
|
||||
</div>
|
||||
<div class="field field-wide">
|
||||
<label class="form-label" for="clientAddress">청소할 곳 주소</label>
|
||||
<input type="text" id="clientAddress" name="clientAddress" autocomplete="off" class="text-input" placeholder="예: 서울시 마포구 공덕동 120" required />
|
||||
</div>
|
||||
<button type="button" class="calc-submit" id="btnSubmitQuote">견적 요청</button>
|
||||
<p class="request-note">예시 화면입니다. 입력한 정보는 저장하거나 전송하지 않습니다.</p>
|
||||
</form>
|
||||
</section>
|
||||
<div class="wrap foot-meta">
|
||||
<p class="foot-brand">청온 케어</p>
|
||||
<p class="foot-contact">전화 02-000-4172</p>
|
||||
<p class="foot-notice">청온 케어는 가상 브랜드 쇼케이스입니다. 서비스, 가격, 접수, 운영 현황, 연락처는 예시입니다.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- 인터랙티브 스크립트 -->
|
||||
<!-- 모바일 하단 고정 행동 바 -->
|
||||
<div class="action-bar" role="group" aria-label="빠른 행동">
|
||||
<button type="button" class="action-bar-call" id="btnCall">전화</button>
|
||||
<a class="action-bar-quote" href="#request">견적 요청</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
// 1. 뷰 모드 전환 (고객 뷰 vs 관리자 뷰)
|
||||
// 1. 화면 전환 (고객 화면 / 운영 화면 예시)
|
||||
const btnClient = document.getElementById("btnModeClient");
|
||||
const btnAdmin = document.getElementById("btnModeAdmin");
|
||||
|
||||
function setViewMode(mode) {
|
||||
document.body.setAttribute("data-view", mode);
|
||||
if (mode === "admin") {
|
||||
btnAdmin.classList.add("is-active");
|
||||
btnClient.classList.remove("is-active");
|
||||
} else {
|
||||
btnClient.classList.add("is-active");
|
||||
btnAdmin.classList.remove("is-active");
|
||||
}
|
||||
const adminOn = mode === "admin";
|
||||
btnAdmin.classList.toggle("is-active", adminOn);
|
||||
btnClient.classList.toggle("is-active", !adminOn);
|
||||
btnAdmin.setAttribute("aria-pressed", String(adminOn));
|
||||
btnClient.setAttribute("aria-pressed", String(!adminOn));
|
||||
}
|
||||
|
||||
btnClient.addEventListener("click", () => setViewMode("client"));
|
||||
btnAdmin.addEventListener("click", () => setViewMode("admin"));
|
||||
|
||||
// 단축키 Alt + A 로 관리자 모드 토글
|
||||
// 단축키 Alt + A — 입력 중에는 무시한다
|
||||
window.addEventListener("keydown", (e) => {
|
||||
const tag = (e.target && e.target.tagName) || "";
|
||||
if (/^(INPUT|TEXTAREA|SELECT)$/.test(tag)) return;
|
||||
if (e.altKey && (e.key === "a" || e.key === "A" || e.key === "ㅁ")) {
|
||||
const cur = document.body.getAttribute("data-view");
|
||||
setViewMode(cur === "admin" ? "client" : "admin");
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 견적 계산기 로직
|
||||
// 2. 견적 계산
|
||||
const pyeongSlider = document.getElementById("pyeongSlider");
|
||||
const pyeongValue = document.getElementById("pyeongValue");
|
||||
const sumPyeong = document.getElementById("sumPyeong");
|
||||
const sumBasePrice = document.getElementById("sumBasePrice");
|
||||
const sumAddonPrice = document.getElementById("sumAddonPrice");
|
||||
const sumTotal = document.getElementById("sumTotal");
|
||||
const requestTotal = document.getElementById("requestTotal");
|
||||
const sumSpaceType = document.getElementById("sumSpaceType");
|
||||
const typeBtns = document.querySelectorAll(".type-btn");
|
||||
const addonCheckboxes = document.querySelectorAll("input[name='addon']");
|
||||
|
|
@ -528,45 +452,45 @@
|
|||
function updateQuote() {
|
||||
const pyeong = parseInt(pyeongSlider.value, 10);
|
||||
const sqm = Math.round(pyeong * 3.30578);
|
||||
pyeongValue.textContent = `${pyeong} 평 (약 ${sqm}㎡)`;
|
||||
sumPyeong.textContent = `${pyeong}평 (평당 ${currentBaseRate.toLocaleString()}원)`;
|
||||
pyeongValue.textContent = `${pyeong}평 (약 ${sqm}㎡)`;
|
||||
sumPyeong.textContent = `${pyeong}평 (평당 ${currentBaseRate.toLocaleString("ko-KR")}원)`;
|
||||
sumSpaceType.textContent = currentTypeLabel;
|
||||
|
||||
const baseCost = pyeong * currentBaseRate;
|
||||
sumBasePrice.textContent = `${baseCost.toLocaleString()}원`;
|
||||
sumBasePrice.textContent = `${baseCost.toLocaleString("ko-KR")}원`;
|
||||
|
||||
let addonCost = 0;
|
||||
addonCheckboxes.forEach((cb) => {
|
||||
if (cb.checked) {
|
||||
addonCost += parseInt(cb.getAttribute("data-price"), 10);
|
||||
}
|
||||
if (cb.checked) addonCost += parseInt(cb.getAttribute("data-price"), 10);
|
||||
});
|
||||
sumAddonPrice.textContent = `${addonCost.toLocaleString()}원`;
|
||||
sumAddonPrice.textContent = `${addonCost.toLocaleString("ko-KR")}원`;
|
||||
|
||||
const total = baseCost + addonCost;
|
||||
sumTotal.textContent = `${total.toLocaleString()}원`;
|
||||
const totalStr = `${total.toLocaleString("ko-KR")}원`;
|
||||
sumTotal.textContent = totalStr;
|
||||
requestTotal.textContent = totalStr;
|
||||
}
|
||||
|
||||
pyeongSlider.addEventListener("input", updateQuote);
|
||||
|
||||
typeBtns.forEach((btn) => {
|
||||
btn.addEventListener("click", () => {
|
||||
typeBtns.forEach((b) => b.classList.remove("is-active"));
|
||||
typeBtns.forEach((b) => {
|
||||
b.classList.remove("is-active");
|
||||
b.setAttribute("aria-pressed", "false");
|
||||
});
|
||||
btn.classList.add("is-active");
|
||||
btn.setAttribute("aria-pressed", "true");
|
||||
currentBaseRate = parseInt(btn.getAttribute("data-base"), 10);
|
||||
currentTypeLabel = btn.textContent.trim();
|
||||
updateQuote();
|
||||
});
|
||||
});
|
||||
|
||||
addonCheckboxes.forEach((cb) => {
|
||||
cb.addEventListener("change", updateQuote);
|
||||
});
|
||||
|
||||
// 초기 계산 1회 실행
|
||||
addonCheckboxes.forEach((cb) => cb.addEventListener("change", updateQuote));
|
||||
updateQuote();
|
||||
|
||||
// 3. 견적 신청 버튼 클릭 -> 관리자 원장에 즉시 추가되는 풀-루프 인터랙션!
|
||||
// 3. 견적 요청 → 운영 화면 예시 표에 한 줄 추가
|
||||
const btnSubmit = document.getElementById("btnSubmitQuote");
|
||||
const tableBody = document.getElementById("adminTableBody");
|
||||
const kpiNewCount = document.getElementById("kpiNewCount");
|
||||
|
|
@ -582,30 +506,58 @@
|
|||
submissionCount++;
|
||||
kpiNewCount.textContent = `${submissionCount}건`;
|
||||
|
||||
// 새 행을 관리자 테이블 최상단에 삽입
|
||||
const newRow = document.createElement("tr");
|
||||
newRow.style.backgroundColor = "var(--accent-light)";
|
||||
newRow.innerHTML = `
|
||||
<td class="mono">#CO-2026-082${submissionCount}</td>
|
||||
<td><strong>${name}</strong><br /><span style="color:var(--ink-muted);font-size:11px;">${phone}</span></td>
|
||||
<td>${currentTypeLabel} (${pyeong}평)</td>
|
||||
<td>${address}</td>
|
||||
<td class="mono" style="font-weight:700;color:var(--accent);">${totalStr}</td>
|
||||
<td>배차 지정 대기</td>
|
||||
<td><span class="status-pill new">방금 접수됨</span></td>
|
||||
<td><button class="action-btn" onclick="alert('배차 팀장을 매칭 중입니다.');">배차 지정</button></td>
|
||||
`;
|
||||
newRow.className = "row-fresh";
|
||||
const cells = [
|
||||
["num", `#CO-2026-082${submissionCount}`],
|
||||
["", ""],
|
||||
["", `${currentTypeLabel} (${pyeong}평)`],
|
||||
["", address],
|
||||
["num cell-strong cell-accent", totalStr],
|
||||
["", "배차 지정 대기"],
|
||||
["", ""],
|
||||
["", ""],
|
||||
];
|
||||
cells.forEach(([cls, text], i) => {
|
||||
const td = document.createElement("td");
|
||||
if (cls) td.className = cls;
|
||||
if (i === 1) {
|
||||
const strong = document.createElement("strong");
|
||||
strong.textContent = name;
|
||||
const sub = document.createElement("span");
|
||||
sub.className = "cell-sub";
|
||||
sub.textContent = phone;
|
||||
td.append(strong, document.createElement("br"), sub);
|
||||
} else if (i === 6) {
|
||||
const pill = document.createElement("span");
|
||||
pill.className = "status-pill new";
|
||||
pill.textContent = "방금 접수됨";
|
||||
td.append(pill);
|
||||
} else if (i === 7) {
|
||||
const b = document.createElement("button");
|
||||
b.type = "button";
|
||||
b.className = "action-btn";
|
||||
b.textContent = "배차 지정";
|
||||
b.addEventListener("click", () => alert("배차 팀장을 매칭 중입니다. 예시 화면이라 실제 배차는 진행되지 않습니다."));
|
||||
td.append(b);
|
||||
} else {
|
||||
td.textContent = text;
|
||||
}
|
||||
newRow.append(td);
|
||||
});
|
||||
tableBody.insertBefore(newRow, tableBody.firstChild);
|
||||
|
||||
alert(`${name}님의 예상 견적은 ${totalStr}입니다.\n실제 견적·신청은 진행되지 않았으며 입력 정보는 저장하거나 전송하지 않습니다.`);
|
||||
alert(`${name}님의 예상 견적은 ${totalStr}입니다.\n실제 견적과 신청은 진행되지 않았으며 입력 정보는 저장하거나 전송하지 않습니다.`);
|
||||
});
|
||||
|
||||
// 모달 열기
|
||||
// 4. 다이얼로그
|
||||
const btnOpenQc = document.getElementById("btnOpenQcModal");
|
||||
const qcModal = document.getElementById("qcModal");
|
||||
if (btnOpenQc && qcModal) {
|
||||
btnOpenQc.addEventListener("click", () => qcModal.showModal());
|
||||
}
|
||||
if (btnOpenQc && qcModal) btnOpenQc.addEventListener("click", () => qcModal.showModal());
|
||||
|
||||
const btnCall = document.getElementById("btnCall");
|
||||
const callDialog = document.getElementById("callDialog");
|
||||
if (btnCall && callDialog) btnCall.addEventListener("click", () => callDialog.showModal());
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue