서비스 운영 종료 안내와 모달 가독성 개선
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800;900&family=Noto+Sans+KR:wght@400;700;900&display=swap" rel="stylesheet" />
|
||||
<title>관리자 - UNIARE</title>
|
||||
</head>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uadeck-api",
|
||||
"version": "4.0.28",
|
||||
"version": "4.0.29",
|
||||
"type": "module",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
<title>Card List</title>
|
||||
<script src="/script/navigation.js"></script>
|
||||
<script src="/script/api.js"></script>
|
||||
<link rel="stylesheet" href="./style/output.css" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link rel="stylesheet" href="./style/auth-header.css" />
|
||||
<script type="module" src="/i18n/i18n.js"></script>
|
||||
<link href="/style/navigation.css" rel="stylesheet" />
|
||||
<link href="/style/style.css" rel="stylesheet" />
|
||||
<link href="/style/output.css" rel="stylesheet" />
|
||||
<link href="/style/output.css?v=4.0.29" rel="stylesheet" />
|
||||
<style>
|
||||
body { background-color: #f8fafc;}
|
||||
#card-grid { padding-bottom: 180px !important;}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4516420168710424" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.8" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800;900&family=Noto+Sans+KR:wght@400;700;900&display=swap" rel="stylesheet" />
|
||||
<title>내 덱 관리 - UNIARE</title>
|
||||
</head>
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# 변경사항
|
||||
|
||||
## v4.0.29
|
||||
|
||||
### 서비스 운영 종료 안내
|
||||
|
||||
서비스 운영 방향과 제반 여건을 종합적으로 검토한 결과, UNIARE는 **한국 시간 기준 2026년 12월 11일까지 운영**합니다. 그동안 이용해 주신 모든 분께 감사드립니다.
|
||||
|
||||
보관하고 싶은 덱은 운영 종료 전에 덱 결과 화면에서 PNG 이미지로 다운로드해 주세요.
|
||||
|
||||
종료 일정을 확인할 수 있도록 사이트 접속 시 안내창을 표시합니다. 반복 안내를 줄이려면 `1주일간 보지 않기`를 체크한 뒤 `확인`을 누르세요. 같은 브라우저에서 7일 동안 안내창이 표시되지 않습니다.
|
||||
|
||||
### 안내창 가독성 개선
|
||||
|
||||
안내를 편하게 읽을 수 있도록 배경과 글자·버튼의 강조를 부드럽게 조정했습니다. 모바일에서도 한글이 단어 중간에서 끊기지 않도록 줄바꿈을 정리했습니다.
|
||||
|
||||
## v4.0.28
|
||||
|
||||
### Re:제로 EX17BT 카드 추가
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
4. API나 Docker 설정 반영: `4. 전체 업데이트`
|
||||
|
||||
로컬 주소는 `http://localhost:44082`, 운영 주소는 `https://uniare.sori.studio`이다.
|
||||
Git 저장소는 `https://git.sori.studio/sori.studio/uniare.sori.studio.git`이다.
|
||||
Git 저장소는 `https://git.noname.company/sori.studio/uniare.sori.studio.git`이다.
|
||||
|
||||
## 시작 전 확인
|
||||
|
||||
@@ -18,6 +18,12 @@ Git 저장소는 `https://git.sori.studio/sori.studio/uniare.sori.studio.git`이
|
||||
- 카드 이미지는 Git LFS로 관리한다.
|
||||
- 로컬 위치는 `<LOCAL_PROJECT_DIR>/uniare.sori.studio`, NAS 위치는 `<NAS_PROJECT_DIR>/uniare.sori.studio`로 표기한다.
|
||||
|
||||
기존에 받은 프로젝트는 프로젝트 폴더에서 다음 명령으로 원격 주소를 변경한다.
|
||||
|
||||
```bash
|
||||
git remote set-url origin https://git.noname.company/sori.studio/uniare.sori.studio.git
|
||||
```
|
||||
|
||||
## 1. 로컬 실행
|
||||
|
||||
최초 한 번 프로젝트 폴더에서 `cp .env.example .env`를 실행한다.
|
||||
@@ -48,7 +54,7 @@ NAS에 Git, Git LFS, Docker, Docker Compose가 설치되어 있어야 한다.
|
||||
|
||||
```bash
|
||||
cd <NAS_PROJECT_DIR>
|
||||
git clone https://git.sori.studio/sori.studio/uniare.sori.studio.git uniare.sori.studio
|
||||
git clone https://git.noname.company/sori.studio/uniare.sori.studio.git uniare.sori.studio
|
||||
cd uniare.sori.studio
|
||||
git lfs pull
|
||||
cp .env.example .env
|
||||
@@ -79,7 +85,7 @@ API 확인: `curl -fsS http://localhost:44082/api/v1/health`
|
||||
|
||||
운영 지표 확인: `curl -fsS http://localhost:44082/api/stats`
|
||||
|
||||
정상이면 `{"ok":true,"version":"4.0.16"}`이 표시된다.
|
||||
정상이면 `{"ok":true,"version":"4.0.29"}`이 표시된다.
|
||||
|
||||
이메일 기능 확인:
|
||||
|
||||
@@ -173,6 +179,19 @@ curl -s http://127.0.0.1:44082/script/deck-favorites.js | tail -1
|
||||
|
||||
HTML·`style/`·`script/`만 바뀐 경우 API 컨테이너 재시작은 필요 없다.
|
||||
|
||||
### v4.0.29 종료 안내 반영·확인
|
||||
|
||||
종료 안내는 정적 파일 변경이다. 로컬에서 `npm run build:css`로 생성한 `style/output.css`를 함께 반영하고, NAS에서는 위의 `git pull --ff-only`와 `git lfs pull`을 실행한다.
|
||||
|
||||
1. 홈과 직접 접속한 카드 목록·로그인 화면에서 마지막 운영일이 한국 시간 기준 `2026년 12월 11일`로 표시되는지 확인한다.
|
||||
2. 일반 `확인` 후 새로고침하면 안내가 다시 나타나는지 확인한다.
|
||||
3. `1주일간 보지 않기`를 체크하고 `확인`한 뒤 새로고침하거나 다른 화면으로 이동해도 안내가 숨겨지는지 확인한다.
|
||||
4. 브라우저 개발자 도구의 Application → Local Storage에서 `uniare.serviceNotice.hiddenUntil`을 삭제하면 다시 확인할 수 있다. 다른 로그인·덱 저장값은 삭제하지 않는다.
|
||||
5. 한국어·일본어·영어와 모바일 화면에서 안내 문구와 버튼을 확인한다. 저장소가 차단된 환경에서도 안내를 닫을 수 있어야 한다.
|
||||
6. 모바일에서 배경·제목·날짜·버튼이 부드럽게 표시되고, 한글 단어가 중간에서 끊기지 않으며 긴 단어가 모달 밖으로 넘치지 않는지 확인한다.
|
||||
|
||||
이번 변경은 종료 안내만 제공하며 실제 서비스 자동 차단·데이터 삭제·외부 위젯 변경은 포함하지 않는다. 실행 중인 API의 버전 응답도 `4.0.29`로 맞추려면 `docker compose -f docker-compose.prod.yml up -d --build uniare-api`를 추가로 실행한다.
|
||||
|
||||
이메일 기능은 API와 Compose 환경 변수가 함께 바뀌므로 `git pull`만으로 반영되지 않는다. 반드시 `.env` 설정 후 전체 스택을 다시 빌드한다.
|
||||
|
||||
## 4. 전체 업데이트
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 의사결정 이력
|
||||
|
||||
## 2026-11-12 v4.0.29 — 종료 안내는 가벼운 공통 모달과 브라우저별 7일 숨김으로 제공
|
||||
|
||||
💡 모든 진입 화면에서 마지막 운영일을 알리되 반복 안내와 과한 시각적 강조를 줄이고, 모바일에서도 한글 단어를 편하게 읽게 하기 위함.
|
||||
🔧 12개 화면에 3개 언어 안내·2026년 12월 11일까지 운영·PNG 보관 방법을 제공하고, 7일 숨김·옅은 오버레이·단어 단위 줄바꿈을 적용.
|
||||
|
||||
## 2026-10-24 v4.0.28 — Re:제로 EX17BT와 기존 시리즈 이미지를 함께 보강
|
||||
|
||||
💡 신규 카드를 제공하면서 이미지가 준비된 기존 패러렐 판본도 같은 배포 단위로 보강하기 위함.
|
||||
|
||||
@@ -76,6 +76,13 @@ i18n/translations.en.json
|
||||
페이지 도움말
|
||||
script/page-help.js
|
||||
|
||||
서비스 운영 종료 안내·7일 숨김
|
||||
script/service-notice.js
|
||||
루트 HTML 12개 화면
|
||||
i18n/translations.ko.json
|
||||
i18n/translations.ja.json
|
||||
i18n/translations.en.json
|
||||
|
||||
덱 공개 기본값
|
||||
script/deck-prefs.js
|
||||
|
||||
|
||||
15
docs/spec.md
15
docs/spec.md
@@ -3,7 +3,7 @@
|
||||
## 프로젝트 개요
|
||||
|
||||
- 서비스명: `UNIARE - Union Arena Deck Builder`
|
||||
- 현재 버전: `v4.0.28`
|
||||
- 현재 버전: `v4.0.29`
|
||||
- 프론트: 정적 HTML, CSS, JavaScript
|
||||
- 백엔드: Express, SQLite(`better-sqlite3`)
|
||||
- 운영: Docker Compose 기반 Nginx + API
|
||||
@@ -29,6 +29,18 @@
|
||||
| `/admin.html` | 회원과 덱 관리 |
|
||||
| `/d/<shareCode>` | Nginx에서 `cardList.html?d=<shareCode>`로 연결 |
|
||||
|
||||
### 서비스 운영 종료 안내
|
||||
|
||||
- 루트 HTML 12개 화면에서 접속 시 공통 종료 안내 모달을 표시한다. 공유 링크도 카드 목록 화면으로 연결되어 같은 안내를 제공한다.
|
||||
- 모달은 옅은 배경 오버레이와 절제된 제목·날짜·버튼 강조를 사용하며, 단어 단위 줄바꿈(`word-break: keep-all`)과 긴 단어의 넘침 방지(`overflow-wrap: break-word`)를 적용한다.
|
||||
- 한국어·일본어·영어를 지원하며 마지막 운영일을 한국 시간 기준 **2026년 12월 11일**로 안내한다.
|
||||
- 종료 사유는 “서비스 운영 방향과 제반 여건을 종합적으로 검토한 결과, 서비스 운영을 종료하게 되었습니다.”로 안내한다.
|
||||
- 보관할 덱은 운영 종료 전에 덱 결과 화면에서 PNG 이미지로 다운로드하도록 안내한다.
|
||||
- 일반 `확인`은 현재 모달만 닫으며 다음 접속 시 다시 표시한다. `1주일간 보지 않기`를 체크한 상태로 닫으면(`확인` 또는 Escape) 해당 브라우저에서 닫은 시각부터 7일 동안 모든 화면의 안내를 숨긴다.
|
||||
- 숨김 만료 시각은 `localStorage`의 `uniare.serviceNotice.hiddenUntil`에 저장한다. 기간이 만료되거나 저장값이 유효하지 않으면 다시 표시한다.
|
||||
- 브라우저 저장소 접근에 실패해도 안내 표시와 닫기는 사용할 수 있다. 저장소 사용이 차단되면 7일 숨김은 유지되지 않는다.
|
||||
- 안내는 서비스 자동 차단이나 데이터 삭제를 수행하지 않는다. API와 외부 위젯 동작은 유지한다.
|
||||
|
||||
## 검색 노출
|
||||
|
||||
- 메인 검색 제목은 `UNIARE | 유니온 아레나 덱 빌더`를 사용한다.
|
||||
@@ -96,6 +108,7 @@
|
||||
| `uadeck_token` | JWT. 로그인 유지 선택 시 `localStorage`, 미선택 시 `sessionStorage` |
|
||||
| `uadeck_user` | 로그인 사용자 캐시. 토큰과 같은 저장소 사용 |
|
||||
| `uadeck.deckFavorites` | 비로그인 즐겨찾기 및 로그인 시 최초 이전 대상 |
|
||||
| `uniare.serviceNotice.hiddenUntil` | 종료 안내를 숨길 만료 시각. 체크한 상태로 닫은 시점부터 7일 동안 전체 화면에 적용 |
|
||||
|
||||
## 인증 및 권한
|
||||
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# 업데이트 이력
|
||||
|
||||
## 2026-11-12 / v4.0.29 — 서비스 종료 안내 및 모달 가독성 개선
|
||||
|
||||
### 수행 작업
|
||||
- 루트 HTML 12개 화면에 한국어·일본어·영어 공통 종료 안내 모달 연결
|
||||
- 한국 시간 기준 2026년 12월 11일까지 운영, 포괄적인 종료 사유와 덱 PNG 보관 방법 안내
|
||||
- `1주일간 보지 않기` 체크 후 닫으면 브라우저별로 7일 동안 안내 숨김
|
||||
- 저장소 접근·번역 로딩 실패 시에도 기본 한국어 안내 표시와 닫기 유지
|
||||
- 배경 오버레이를 25%로 낮추고 흐림 효과 제거, 그림자·제목·날짜·버튼 강조 완화
|
||||
- 단어 단위 줄바꿈과 긴 단어 넘침 방지를 적용하고 모바일 하단 버튼 배치 정리
|
||||
- VERSION·API 버전과 모달·CSS 캐시 버전을 v4.0.29로 통일
|
||||
- Git 저장소를 새 주소로 변경하고 배포 문서에 기존 프로젝트의 원격 주소 변경 명령 추가
|
||||
|
||||
### 검증
|
||||
- CSS 빌드·JavaScript 문법 검사·`git diff --check` 통과
|
||||
- 임시 DOM 하네스 12개 검증 통과: 표시·닫기·7일 만료 경계·화면 간 숨김·저장소 예외·번역 실패·3개 언어·중복 초기화·Escape 닫기
|
||||
- 루트 HTML 12개 연결·단어 줄바꿈 및 25% 오버레이 CSS 생성·VERSION과 API 버전 일치 확인
|
||||
- 새 Git 저장소 접속 및 기존 main 이력 확인, 최신 카드 데이터 변경을 유지하며 통합
|
||||
- 브라우저 연결을 사용할 수 없어 실제 렌더링·포커스 동작 검증 미수행, 운영 배포 미수행
|
||||
|
||||
## 2026-10-24 / v4.0.28 — Re:제로 EX17BT 카드·패러렐 이미지 추가
|
||||
|
||||
### 수행 작업
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<title>비밀번호 찾기 - UNIARE</title>
|
||||
</head>
|
||||
<body class="app-page">
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
{
|
||||
"serviceNoticeTitle": "Service closure notice",
|
||||
"serviceNoticeThanks": "Thank you for using UNIARE and for all your support.",
|
||||
"serviceNoticeReason": "After reviewing our service direction and overall operating circumstances, we have decided to bring the service to a close.",
|
||||
"serviceNoticeDateLabel": "Last day of service",
|
||||
"serviceNoticeDate": "December 11, 2026 (Korea Standard Time)",
|
||||
"serviceNoticeBackup": "Before the service ends, please download any decks you wish to keep as PNG images from the deck results page.",
|
||||
"serviceNoticeClosing": "We will do our best to keep the service running smoothly until the final day. Thank you for being part of UNIARE.",
|
||||
"serviceNoticeHideWeek": "Do not show for 1 week",
|
||||
"serviceNoticeConfirm": "OK",
|
||||
"mainTitle": "Master Your Strategy",
|
||||
"mainDesc": "Explore all Union Arena series at a glance and<br class='hidden sm:block' /> build the ultimate deck that fits your strategy.",
|
||||
"back": "← BACK",
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
{
|
||||
"serviceNoticeTitle": "サービス終了のお知らせ",
|
||||
"serviceNoticeThanks": "これまでUNIAREをご利用いただき、誠にありがとうございます。",
|
||||
"serviceNoticeReason": "サービスの運営方針や諸般の事情を総合的に検討した結果、サービスを終了することとなりました。",
|
||||
"serviceNoticeDateLabel": "サービス最終提供日",
|
||||
"serviceNoticeDate": "2026年12月11日(韓国時間)",
|
||||
"serviceNoticeBackup": "保存しておきたいデッキは、終了前にデッキ結果画面からPNG画像としてダウンロードしてください。",
|
||||
"serviceNoticeClosing": "最終日まで安心してご利用いただけるよう努めてまいります。これまでのご愛顧に心より感謝申し上げます。",
|
||||
"serviceNoticeHideWeek": "1週間表示しない",
|
||||
"serviceNoticeConfirm": "確認",
|
||||
"mainTitle": "Master Your Strategy",
|
||||
"mainDesc": "ユニオンアリーナの全シリーズを一目で確認し、<br class='hidden sm:block' /> あなたの戦略に最適なデッキを構築してみてください。",
|
||||
"back": "← 戻る",
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
{
|
||||
"serviceNoticeTitle": "서비스 운영 종료 안내",
|
||||
"serviceNoticeThanks": "그동안 UNIARE를 이용해 주셔서 진심으로 감사합니다.",
|
||||
"serviceNoticeReason": "서비스 운영 방향과 제반 여건을 종합적으로 검토한 결과, 서비스 운영을 종료하게 되었습니다.",
|
||||
"serviceNoticeDateLabel": "서비스 운영 마지막 날",
|
||||
"serviceNoticeDate": "2026년 12월 11일 (한국 시간)",
|
||||
"serviceNoticeBackup": "보관하고 싶은 덱은 종료 전에 덱 결과 화면에서 PNG 이미지로 다운로드해 주세요.",
|
||||
"serviceNoticeClosing": "마지막까지 이용에 불편이 없도록 최선을 다하겠습니다. 그동안 함께해 주신 모든 분께 감사드립니다.",
|
||||
"serviceNoticeHideWeek": "1주일간 보지 않기",
|
||||
"serviceNoticeConfirm": "확인",
|
||||
"mainTitle": "Master Your Strategy",
|
||||
"mainDesc": "유니온 아레나의 모든 시리즈를 한눈에 확인하고,<br class='hidden sm:block' /> 당신의 전략에 맞는 최고의 덱을 구축해 보세요.",
|
||||
"back": "← 뒤로 가기",
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4516420168710424" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="./style/output.css" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link rel="stylesheet" href="./style/brand.css" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Noto+Sans+KR:wght@400;700&display=swap" rel="stylesheet" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800;900&family=Noto+Sans+KR:wght@400;700;900&display=swap" rel="stylesheet" />
|
||||
<title>로그인 - UNIARE</title>
|
||||
</head>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4516420168710424" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.8" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800;900&family=Noto+Sans+KR:wght@400;700;900&display=swap" rel="stylesheet" />
|
||||
<title>공개 덱 - UNIARE</title>
|
||||
</head>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4516420168710424" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link rel="stylesheet" href="./style/app-shell.css" />
|
||||
<link rel="stylesheet" href="./style/auth-header.css" />
|
||||
<link rel="stylesheet" href="./style/profile.css" />
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<title>비밀번호 재설정 - UNIARE</title>
|
||||
</head>
|
||||
<body class="app-page">
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4516420168710424" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="./style/output.css" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link rel="stylesheet" href="./style/auth-header.css" />
|
||||
<script src="/script/api.js"></script>
|
||||
<title>Deck Result - UA Deck Builder</title>
|
||||
|
||||
117
script/service-notice.js
Normal file
117
script/service-notice.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* 모든 화면에서 서비스 종료 일정과 브라우저별 7일 숨김 선택을 안내한다.
|
||||
*/
|
||||
(function initServiceNotice() {
|
||||
const STORAGE_KEY = 'uniare.serviceNotice.hiddenUntil';
|
||||
const HIDE_DURATION_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
const SUPPORTED_LANGUAGES = new Set(['ko', 'ja', 'en']);
|
||||
|
||||
/**
|
||||
* URL, 브라우저 저장값 순으로 안내 언어를 선택한다.
|
||||
* @returns {string} 지원 언어 코드
|
||||
*/
|
||||
function getLanguage() {
|
||||
const fromQuery = new URLSearchParams(window.location.search).get('lang');
|
||||
let selected = fromQuery;
|
||||
if (!selected) {
|
||||
try {
|
||||
selected = localStorage.getItem('lang');
|
||||
} catch {
|
||||
selected = 'ko';
|
||||
}
|
||||
}
|
||||
return SUPPORTED_LANGUAGES.has(selected) ? selected : 'ko';
|
||||
}
|
||||
|
||||
/**
|
||||
* 저장소가 차단되었거나 만료값이 유효하지 않으면 안내를 표시한다.
|
||||
* @returns {boolean} 7일 숨김 기간이 남아 있는지 여부
|
||||
*/
|
||||
function isHidden() {
|
||||
try {
|
||||
const hiddenUntil = Number(localStorage.getItem(STORAGE_KEY));
|
||||
return Number.isFinite(hiddenUntil) && hiddenUntil > Date.now();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이지 번역과 같은 키를 사용하고, 로딩 실패 시 한국어 안내를 유지한다.
|
||||
* @param {HTMLDialogElement} dialog 안내 모달
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function translateNotice(dialog) {
|
||||
try {
|
||||
const response = await fetch(`/i18n/translations.${getLanguage()}.json?v=4.0.29`);
|
||||
if (!response.ok) return;
|
||||
const translations = await response.json();
|
||||
dialog.querySelectorAll('[data-i18n]').forEach((element) => {
|
||||
const translated = translations[element.dataset.i18n];
|
||||
if (typeof translated === 'string') element.textContent = translated;
|
||||
});
|
||||
} catch {
|
||||
// 번역 요청 실패가 종료 안내 표시나 닫기를 막지 않도록 한다.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 네이티브 모달로 배경 접근을 막고 키보드 포커스와 Escape 닫기를 제공한다.
|
||||
*/
|
||||
function showNotice() {
|
||||
if (isHidden() || document.getElementById('service-notice')) return;
|
||||
|
||||
const dialog = document.createElement('dialog');
|
||||
dialog.id = 'service-notice';
|
||||
dialog.setAttribute('aria-labelledby', 'service-notice-title');
|
||||
dialog.setAttribute('aria-describedby', 'service-notice-description service-notice-date service-notice-backup');
|
||||
dialog.className = 'm-auto max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-lg overflow-y-auto break-keep [overflow-wrap:break-word] rounded-2xl border border-slate-100 bg-white p-0 text-slate-700 shadow-xl shadow-slate-900/10 backdrop:bg-slate-900/25 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200';
|
||||
dialog.style.fontFamily = 'Pretendard, "Noto Sans KR", sans-serif';
|
||||
dialog.innerHTML = `
|
||||
<div class="p-6 sm:p-8">
|
||||
<h2 id="service-notice-title" data-i18n="serviceNoticeTitle" class="m-0 text-xl font-semibold tracking-tight">서비스 운영 종료 안내</h2>
|
||||
<p data-i18n="serviceNoticeThanks" class="mt-5 text-sm leading-7 text-slate-600 dark:text-slate-300">그동안 UNIARE를 이용해 주셔서 진심으로 감사합니다.</p>
|
||||
<p id="service-notice-description" data-i18n="serviceNoticeReason" class="mt-3 text-sm leading-7 text-slate-600 dark:text-slate-300">서비스 운영 방향과 제반 여건을 종합적으로 검토한 결과, 서비스 운영을 종료하게 되었습니다.</p>
|
||||
<div class="mt-5 rounded-xl bg-slate-50 px-4 py-3 dark:bg-slate-700/40">
|
||||
<p data-i18n="serviceNoticeDateLabel" class="m-0 text-xs text-slate-500 dark:text-slate-400">서비스 운영 마지막 날</p>
|
||||
<p id="service-notice-date" class="mt-1.5 text-base font-medium"><time datetime="2026-12-11" data-i18n="serviceNoticeDate">2026년 12월 11일 (한국 시간)</time></p>
|
||||
</div>
|
||||
<p id="service-notice-backup" data-i18n="serviceNoticeBackup" class="mt-5 text-sm leading-7 text-slate-600 dark:text-slate-300">보관하고 싶은 덱은 종료 전에 덱 결과 화면에서 PNG 이미지로 다운로드해 주세요.</p>
|
||||
<p data-i18n="serviceNoticeClosing" class="mt-3 text-sm leading-7 text-slate-600 dark:text-slate-300">마지막까지 이용에 불편이 없도록 최선을 다하겠습니다. 그동안 함께해 주신 모든 분께 감사드립니다.</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center justify-between gap-3 border-t border-slate-100 px-6 py-4 sm:px-8 dark:border-slate-700">
|
||||
<label class="flex cursor-pointer items-center gap-2 text-xs text-slate-500 sm:text-sm dark:text-slate-300">
|
||||
<input id="service-notice-hide-week" type="checkbox" class="h-4 w-4 shrink-0 cursor-pointer accent-slate-500 dark:accent-slate-400" />
|
||||
<span data-i18n="serviceNoticeHideWeek">1주일간 보지 않기</span>
|
||||
</label>
|
||||
<button id="service-notice-confirm" type="button" autofocus data-i18n="serviceNoticeConfirm" class="cursor-pointer rounded-lg border border-slate-200 bg-slate-50 px-5 py-2.5 text-sm font-medium text-slate-600 hover:bg-slate-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-400 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200 dark:hover:bg-slate-600">확인</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const previousOverflow = document.documentElement.style.overflow;
|
||||
const hideWeek = dialog.querySelector('#service-notice-hide-week');
|
||||
dialog.querySelector('#service-notice-confirm').addEventListener('click', () => dialog.close());
|
||||
dialog.addEventListener('close', () => {
|
||||
if (hideWeek.checked) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, String(Date.now() + HIDE_DURATION_MS));
|
||||
} catch {
|
||||
// 저장소를 사용할 수 없어도 현재 화면의 안내는 정상적으로 닫는다.
|
||||
}
|
||||
}
|
||||
document.documentElement.style.overflow = previousOverflow;
|
||||
dialog.remove();
|
||||
}, { once: true });
|
||||
|
||||
document.body.appendChild(dialog);
|
||||
dialog.showModal();
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
translateNotice(dialog);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', showNotice, { once: true });
|
||||
} else {
|
||||
showNotice();
|
||||
}
|
||||
})();
|
||||
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800;900&family=Noto+Sans+KR:wght@400;700;900&display=swap" rel="stylesheet" />
|
||||
<title>회원가입 - UNIARE</title>
|
||||
</head>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.16" />
|
||||
<link rel="stylesheet" href="./style/output.css?v=4.0.29" />
|
||||
<script src="/script/service-notice.js?v=4.0.29" defer></script>
|
||||
<title>이메일 인증 - UNIARE</title>
|
||||
</head>
|
||||
<body class="app-page">
|
||||
|
||||
Reference in New Issue
Block a user