Files
happy-life-star/web-prototype/onboarding.js
T
2026-02-27 11:32:50 +08:00

152 lines
8.0 KiB
JavaScript

import { state } from './state.js';
import { UI } from './components.js';
export const Onboarding = {
onComplete: null,
render(onCompleteCallback) {
if (onCompleteCallback) this.onComplete = onCompleteCallback;
const container = document.getElementById('view-container');
container.innerHTML = `
<div id="onboarding-root" class="w-full h-full glass-card p-10 flex flex-col justify-between overflow-hidden relative">
<div id="step-content" class="flex-1 flex flex-col justify-center max-w-2xl mx-auto w-full"></div>
<div class="flex items-center justify-between mt-10 max-w-2xl mx-auto w-full border-t border-white/5 pt-8">
<div id="step-indicator" class="flex gap-2">
${[1,2,3,4,5].map(i => `<div class="step-dot-${i} w-3 h-1 rounded-full bg-white/10 transition-all duration-500"></div>`).join('')}
</div>
<div class="flex gap-4">
<button id="prev-step" class="hidden text-white/40 px-6 py-2 text-sm hover:text-white transition-colors">返回</button>
<button id="next-step" class="glass-btn px-8 py-3 rounded-full text-orange-200 font-bold tracking-widest text-sm shadow-xl shadow-orange-900/10">
下一章 <i data-lucide="arrow-right" class="w-4 h-4 ml-2"></i>
</button>
</div>
</div>
</div>
`;
this.renderStep(state.currentStep || 1);
this.initEvents();
},
renderStep(step) {
const content = document.getElementById('step-content');
const nextBtn = document.getElementById('next-step');
const prevBtn = document.getElementById('prev-step');
for(let i=1; i<=5; i++){
const dot = document.querySelector(`.step-dot-${i}`);
if(dot) dot.className = `step-dot-${i} h-1 rounded-full transition-all duration-500 ${i === step ? 'w-8 bg-orange-200' : 'w-3 bg-white/10'}`;
}
prevBtn.classList.toggle('hidden', step === 1);
nextBtn.innerHTML = step === 5 ? '开启人生 <i data-lucide="check" class="w-4 h-4 ml-2"></i>' : '继续 <i data-lucide="arrow-right" class="w-4 h-4 ml-2"></i>';
let html = '';
if (step === 1) {
html = `
<div class="animate-fade-in space-y-8">
<div class="mb-6">
<h2 class="text-4xl font-serif mb-3">你是谁?</h2>
<p class="text-white/40 italic text-sm">定义你生命坐标的初始属性。</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-2">
${UI.renderInput('称呼', 'reg-nickname', 'text', '例如:林中鹿', state.registrationData.nickname)}
${UI.renderInput('性别', 'reg-gender', 'text', '自由填写', state.registrationData.gender)}
${UI.renderInput('MBTI', 'reg-mbti', 'text', '如:INFJ', state.registrationData.mbti)}
${UI.renderInput('星座', 'reg-zodiac', 'text', '星辰指引', state.registrationData.zodiac)}
</div>
${UI.renderInput('兴趣爱好', 'reg-hobbies', 'text', '用逗号分隔你的热爱', (state.registrationData.hobbies || []).join(','))}
</div>
`;
} else if (step === 2) {
html = this.renderMemoryStep('那段纯真的时光', '童年记忆', 'reg-child-text', 'reg-child-date', 'childhood', state.registrationData.childhood);
} else if (step === 3) {
html = this.renderMemoryStep('光芒闪耀的时刻', '开心的经历', 'reg-joy-text', 'reg-joy-date', 'joy', state.registrationData.joy);
} else if (step === 4) {
html = this.renderMemoryStep('在暗夜中潜行', '沮丧与低谷', 'reg-low-text', 'reg-low-date', 'low', state.registrationData.low);
} else if (step === 5) {
html = `
<div class="animate-fade-in space-y-8">
<div class="mb-6">
<h2 class="text-4xl font-serif mb-3">未来想成为谁?</h2>
<p class="text-white/40 italic text-sm">勾勒你对理想生活的全部向往。</p>
</div>
${UI.renderTextArea('对未来的憧憬', 'reg-future-vision', '你想成为一个什么样的人?', state.registrationData.future.vision || '')}
${UI.renderTextArea('理想生活状态', 'reg-future-ideal', '你的理想清晨与傍晚是怎样的?', state.registrationData.future.ideal || '')}
</div>
`;
}
content.innerHTML = html;
lucide.createIcons();
},
renderMemoryStep(title, label, textId, dateId, type, data) {
return `
<div class="animate-fade-in space-y-6">
<div>
<h2 class="text-4xl font-serif mb-3">${title}</h2>
<p class="text-white/40 italic text-sm">回望足迹,这些瞬间如何塑造了此时的你。</p>
</div>
<div class="space-y-4">
<div class="flex flex-col gap-2">
<label class="text-[10px] text-white/30 uppercase tracking-widest font-bold">${label}的日期</label>
<input type="date" id="${dateId}" value="${data.date || ''}" class="glass-input max-w-xs">
</div>
<div class="space-y-2">
<label class="text-[10px] text-white/30 uppercase tracking-widest font-bold">详细描述</label>
<textarea id="${textId}" rows="5" class="glass-input w-full text-sm" placeholder="描述那段时光发生的点滴...">${data.text || ''}</textarea>
</div>
<div class="flex flex-wrap gap-2 pt-2">
${UI.renderInspiration(type, textId)}
</div>
</div>
</div>
`;
},
saveStepData() {
const step = state.currentStep;
if (step === 1) {
state.updateRegistration({
nickname: document.getElementById('reg-nickname').value,
gender: document.getElementById('reg-gender').value,
mbti: document.getElementById('reg-mbti').value,
zodiac: document.getElementById('reg-zodiac').value,
hobbies: document.getElementById('reg-hobbies').value.split(',').map(s => s.trim()).filter(s => s)
});
} else if (step === 2) {
state.updateRegistration({ childhood: { date: document.getElementById('reg-child-date').value, text: document.getElementById('reg-child-text').value } });
} else if (step === 3) {
state.updateRegistration({ joy: { date: document.getElementById('reg-joy-date').value, text: document.getElementById('reg-joy-text').value } });
} else if (step === 4) {
state.updateRegistration({ low: { date: document.getElementById('reg-low-date').value, text: document.getElementById('reg-low-text').value } });
} else if (step === 5) {
state.updateRegistration({
future: { vision: document.getElementById('reg-future-vision').value, ideal: document.getElementById('reg-future-ideal').value }
});
}
},
initEvents() {
document.getElementById('next-step').onclick = () => {
this.saveStepData();
if (state.currentStep < 5) {
state.currentStep++;
this.renderStep(state.currentStep);
} else {
state.view = 'dashboard';
state.save();
if (this.onComplete) this.onComplete();
}
};
document.getElementById('prev-step').onclick = () => {
if (state.currentStep > 1) {
state.currentStep--;
this.renderStep(state.currentStep);
}
};
}
};