mingle-website/js/partner.js
68893236+KINDNICK@users.noreply.github.com 5d2ff03d79 Add: 파트너 스트리머 모집 페이지 추가
- 파트너 스트리머 모집 페이지 (partner.html) 추가
- 선발 로드맵 섹션 구현 (2026.01.10 ~ 2026.12.31)
- 지원 조건 및 혜택 안내
- 지원서 양식 템플릿 및 복사 기능
- 이메일 클릭 시 클립보드 복사 기능
- 반응형 디자인 적용 (모바일 최적화)

Update: 팝업 시스템 개선
- index.html 팝업 이미지 및 링크 업데이트
- 쿠키 기반 "오늘 하루 보지 않기" 기능

Update: 네비게이션 메뉴
- 헤더에 Partner 링크 추가

Update: 서버 설정
- Caddy 리버스 프록시 설정 추가 (HTTPS 지원)
- Python 서버 HTTP 모드 강제 설정

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-10 02:04:29 +09:00

376 lines
12 KiB
JavaScript

// ========================================
// Partner 페이지 전용 JavaScript
// ========================================
document.addEventListener('DOMContentLoaded', function() {
initCopyButton();
initEmailLinkCopy();
});
// 복사 버튼 초기화
function initCopyButton() {
const copyBtn = document.getElementById('copyTemplateBtn');
if (copyBtn) {
copyBtn.addEventListener('click', function() {
copyApplicationTemplate();
});
}
}
// 지원서 양식 복사 함수
function copyApplicationTemplate() {
const templateText = `밍글스튜디오 파트너 스트리머 지원서
[ 기본 정보 ]
1. 현재 데뷔하여 활동하고 계신가요?
답변: (예 / 아니오)
2. 활동하고 계시다면, 활동명은 무엇인가요?
답변:
3. 어떤 방송 플랫폼에서 방송을 하고 계신가요?
답변: (예: 유튜브, 트위치, 아프리카TV, SOOP 등)
4. MCN 또는 기업 소속이신가요?
답변: (예 / 아니오)
※ 소속된 경우, 소속 회사명을 함께 기재해주세요
[ 지원 동기 및 계획 ]
5. 지원하게 된 계기가 무엇인가요?
답변:
6. 파트너 스트리머가 된다면 어떤 콘텐츠를 진행해보고 싶으신가요?
답변:
[ 경험 및 환경 ]
7. 모션 캡처를 경험해보신 적이 있으신가요?
답변: (예 / 아니오)
8. 스튜디오 방문에 어려움이 있으신가요?
※ 스튜디오는 인천광역시 부평구에 위치하고 있습니다
답변: (어려움 없음 / 다소 어렵지만 가능 / 어려움 있음)
9. 본인만의 특기가 있다면?
답변: (방송이나 유튜브 영상 링크 첨부로 대체 가능)
[ 연락처 정보 ]
• 이름:
• 이메일:
• 디스코드 아이디: `;
// 클립보드에 복사
navigator.clipboard.writeText(templateText).then(function() {
// 성공 피드백
const copyBtn = document.getElementById('copyTemplateBtn');
const originalText = copyBtn.querySelector('.copy-text').textContent;
copyBtn.classList.add('copied');
copyBtn.querySelector('.copy-text').textContent = '복사 완료!';
// 2초 후 원래대로 복원
setTimeout(function() {
copyBtn.classList.remove('copied');
copyBtn.querySelector('.copy-text').textContent = originalText;
}, 2000);
// 알림 표시 (commonUtils 사용 가능한 경우)
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('양식이 클립보드에 복사되었습니다!', 'success');
}
}).catch(function(err) {
console.error('복사 실패:', err);
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('복사에 실패했습니다. 다시 시도해주세요.', 'error');
} else {
alert('복사에 실패했습니다. 다시 시도해주세요.');
}
});
}
// 이메일 링크 클릭 시 복사
function initEmailLinkCopy() {
const emailLink = document.getElementById('emailLink');
if (emailLink) {
emailLink.addEventListener('click', function(e) {
e.preventDefault();
const email = this.textContent.trim();
navigator.clipboard.writeText(email).then(function() {
// 성공 알림
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('이메일 주소가 복사되었습니다!', 'success');
}
// 링크 시각적 피드백
emailLink.style.color = '#4CAF50';
setTimeout(function() {
emailLink.style.color = '';
}, 1000);
}).catch(function(err) {
console.error('이메일 복사 실패:', err);
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('복사에 실패했습니다.', 'error');
}
});
});
}
}
// 파트너 지원 폼 초기화 (사용하지 않음 - 삭제 가능)
function initPartnerForm() {
const form = document.getElementById('partnerApplicationForm');
if (form) {
form.addEventListener('submit', handleFormSubmit);
// 실시간 유효성 검사
const inputs = form.querySelectorAll('input, textarea');
inputs.forEach(input => {
if (input.type !== 'radio' && input.type !== 'checkbox') {
input.addEventListener('blur', validateField);
}
});
// 전화번호 자동 포맷팅
const phoneInput = document.getElementById('phone');
if (phoneInput) {
phoneInput.addEventListener('input', formatPhoneNumber);
}
}
}
// 조건부 필드 초기화
function initConditionalFields() {
// MCN/기업 소속 여부에 따라 소속명 입력란 표시
const affiliationRadios = document.querySelectorAll('input[name="hasAffiliation"]');
const affiliationNameInput = document.getElementById('affiliationName');
affiliationRadios.forEach(radio => {
radio.addEventListener('change', function() {
if (this.value === 'yes') {
affiliationNameInput.style.display = 'block';
affiliationNameInput.required = true;
} else {
affiliationNameInput.style.display = 'none';
affiliationNameInput.required = false;
affiliationNameInput.value = '';
}
});
});
}
// 폼 제출 처리
async function handleFormSubmit(e) {
e.preventDefault();
const form = e.target;
const submitBtn = form.querySelector('button[type="submit"]');
// 유효성 검사
if (!validateForm(form)) {
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('모든 필수 항목을 입력해 주세요.', 'error');
} else {
alert('모든 필수 항목을 입력해 주세요.');
}
return;
}
// 개인정보 동의 확인
const privacyAgree = document.getElementById('privacyAgree');
if (!privacyAgree.checked) {
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('개인정보 수집 및 이용에 동의해 주세요.', 'warning');
} else {
alert('개인정보 수집 및 이용에 동의해 주세요.');
}
return;
}
// 제출 버튼 비활성화
const originalText = submitBtn.textContent;
submitBtn.textContent = '제출 중...';
submitBtn.disabled = true;
try {
// 폼 데이터 수집
const formData = new FormData(form);
const data = Object.fromEntries(formData);
// 서버로 전송 (실제 구현 필요)
await submitApplicationForm(data);
// 성공 메시지
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('지원서가 성공적으로 제출되었습니다. 검토 후 연락드리겠습니다!', 'success');
} else {
alert('지원서가 성공적으로 제출되었습니다. 검토 후 연락드리겠습니다!');
}
// 폼 초기화
form.reset();
// 조건부 필드 숨기기
const affiliationNameInput = document.getElementById('affiliationName');
if (affiliationNameInput) {
affiliationNameInput.style.display = 'none';
affiliationNameInput.required = false;
}
} catch (error) {
console.error('Form submission error:', error);
if (window.commonUtils && window.commonUtils.showNotification) {
window.commonUtils.showNotification('전송 중 오류가 발생했습니다. 다시 시도해 주세요.', 'error');
} else {
alert('전송 중 오류가 발생했습니다. 다시 시도해 주세요.');
}
} finally {
// 버튼 복원
submitBtn.textContent = originalText;
submitBtn.disabled = false;
}
}
// 서버 전송 시뮬레이션 (실제 구현 필요)
async function submitApplicationForm(data) {
// 실제 서버 API 엔드포인트로 전송
// 예: await fetch('/api/partner-application', { method: 'POST', body: JSON.stringify(data) })
// 시뮬레이션을 위한 딜레이
return new Promise((resolve) => {
setTimeout(() => {
console.log('Application data:', data);
resolve({ success: true });
}, 1500);
});
}
// 폼 유효성 검사
function validateForm(form) {
let isValid = true;
// 모든 필수 입력 필드 검사
const requiredInputs = form.querySelectorAll('input[required], textarea[required]');
requiredInputs.forEach(input => {
if (!validateField({ target: input })) {
isValid = false;
}
});
// 라디오 버튼 그룹 검사
const requiredRadioGroups = ['isActive', 'hasAffiliation', 'hasMocapExperience', 'canVisit'];
requiredRadioGroups.forEach(groupName => {
const radios = form.querySelectorAll(`input[name="${groupName}"]`);
const checked = Array.from(radios).some(radio => radio.checked);
if (!checked) {
isValid = false;
// 라디오 그룹 에러 표시
const radioGroup = radios[0]?.closest('.form-group');
if (radioGroup) {
radioGroup.style.borderLeft = '4px solid #e74c3c';
}
} else {
const radioGroup = radios[0]?.closest('.form-group');
if (radioGroup) {
radioGroup.style.borderLeft = 'none';
}
}
});
return isValid;
}
// 개별 필드 유효성 검사
function validateField(e) {
const field = e.target;
const value = field.value.trim();
let isValid = true;
let errorMessage = '';
// 필수 필드 확인
if (field.required && !value) {
isValid = false;
errorMessage = '이 항목은 필수입니다.';
}
// 이메일 검사
if (field.type === 'email' && value) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
isValid = false;
errorMessage = '올바른 이메일 형식이 아닙니다.';
}
}
// 전화번호 검사
if (field.type === 'tel' && value) {
const phoneRegex = /^[0-9-]+$/;
if (!phoneRegex.test(value)) {
isValid = false;
errorMessage = '올바른 전화번호 형식이 아닙니다.';
}
}
// 에러 표시
if (!isValid) {
showFieldError(field, errorMessage);
} else {
clearFieldError(field);
}
return isValid;
}
// 필드 에러 표시
function showFieldError(field, message) {
field.style.borderColor = '#e74c3c';
// 기존 에러 메시지 제거
const existingError = field.parentElement.querySelector('.error-message');
if (existingError) {
existingError.remove();
}
// 새 에러 메시지 추가
const errorDiv = document.createElement('div');
errorDiv.className = 'error-message';
errorDiv.style.color = '#e74c3c';
errorDiv.style.fontSize = '0.875rem';
errorDiv.style.marginTop = '0.5rem';
errorDiv.textContent = message;
field.parentElement.appendChild(errorDiv);
}
// 필드 에러 제거
function clearFieldError(field) {
if (field instanceof Event) {
field = field.target;
}
field.style.borderColor = '';
const errorMessage = field.parentElement.querySelector('.error-message');
if (errorMessage) {
errorMessage.remove();
}
}
// 전화번호 자동 포맷팅
function formatPhoneNumber(e) {
const input = e.target;
let value = input.value.replace(/[^0-9]/g, '');
// 자동 하이픈 추가
if (value.length <= 3) {
input.value = value;
} else if (value.length <= 7) {
input.value = value.slice(0, 3) + '-' + value.slice(3);
} else if (value.length <= 11) {
input.value = value.slice(0, 3) + '-' + value.slice(3, 7) + '-' + value.slice(7);
} else {
input.value = value.slice(0, 3) + '-' + value.slice(3, 7) + '-' + value.slice(7, 11);
}
}