jishinExit
セルフ退職支援サービス — あなたの意思を、あなたの言葉で。
全体進捗:20%
退職通知の方法を選択
ご自身の状況に合った通知方法をお選びください。すべての操作はあなた本人の意思に基づき実行されます。
メール予約送信
指定日時に自動送信
PDF・内容証明補助
書面で意思を明確化
電話スクリプト補助
通話記録の補助ログ
メール予約設定
ℹ このメールはあなたの操作のみによって送信されます。内容を必ずご確認のうえ、送信予約を設定してください。
退職スケジュール — タイムライン
STEP 1 · 本日
退職意思の通知(本サービスにて補助)
口頭または書面・メールで上司・人事に伝える
STEP 2 · 2週間後まで(法的最短期間)
退職届の正式提出・受領確認
民法627条:申し出から2週間で退職は有効
STEP 3 · 最終出社日まで
業務引継ぎ・有給消化・備品返却
離職票・源泉徴収票等の書類を受け取る
STEP 4 · 退職翌日〜
健保・年金・失業保険の手続き開始
14日以内に健保・年金の切替が必要
書類の種類を選択
情報の入力
退職時に受け取るべき書類チェックリスト
  • 1
    離職票(1号・2号)
    失業給付申請に必須。退職後10日以内に発行義務あり(雇用保険法)。
    必須
  • 2
    雇用保険被保険者証
    次の就職先に提出が必要。会社が保管していた場合は返却を請求。
    必須
  • 3
    源泉徴収票
    確定申告・転職先の年末調整に使用。退職月の翌月末までに発行義務。
    必須
  • 4
    健康保険資格喪失証明書
    国保加入・任意継続の手続きに必要。速やかに発行を依頼。
    重要
  • 5
    年金手帳(返却される場合)
    会社が保管していた場合は退職時に返却を求める。
    確認
あなたの収支情報を入力
スライダーを動かすと、退職後6ヶ月のキャッシュフローがリアルタイムに更新されます。
28万円
100万円
10日
18万円
5年
有給消化分 収入
失業手当(月額概算)
資金が続く期間
退職後6ヶ月キャッシュフロー予測グラフ
※ 自己都合退職の場合、給付制限期間(原則2ヶ月)後に失業手当が支給開始されます。
※ 基本手当日額は直近6ヶ月の平均賃金の約50〜80%(年齢・賃金により異なる)の概算です。
※ 本シミュレーターは参考値であり、実際の給付額とは異なる場合があります。
AI財務アドバイス Claude AI
シミュレーション結果をもとに、あなたの状況に合ったアドバイスをAIが生成します。
よくある質問(労働法・退職手続き)
退職を引き止められた場合、応じる義務はありますか?
+
民法第627条により、雇用期間の定めのない契約(正社員等)の場合、退職の申し出から2週間経過すれば雇用契約は終了します。会社の同意や就業規則の定める期間にかかわらず、最短2週間で退職は有効です。引き止めに応じる法的義務はありません。ただし、できる限り円満に進めることが実務上の混乱を防ぎます。
有給休暇を消化する権利はありますか?
+
はい。労働基準法第39条により、有給休暇は労働者の権利です。退職前の有給消化は認められており、会社は正当な理由なく拒否できません。会社の「時季変更権」は退職日を越えて行使できないため、実質的に退職前の有給申請を拒否することはできません。
離職票が発行されない場合はどうすればいいですか?
+
離職票の発行は雇用保険法に基づく事業主の義務です。発行を拒否された場合、退職した事業所を管轄するハローワーク(公共職業安定所)に直接相談することで、ハローワークから会社への指導・是正が行われます。また、状況によっては被保険者自身が申請できる場合もあります。
自己都合退職でも失業保険はもらえますか?
+
もらえます。自己都合退職の場合、給付制限期間(原則2ヶ月)を経た後、失業認定を受けることで基本手当(失業保険)が支給されます。受給期間は勤続年数等によって90〜150日です。なお、ハラスメントや劣悪な労働環境等の正当な理由がある場合は「特定理由離職者」として給付制限なしになる場合があります。
退職届と退職願の違いは何ですか?
+
「退職願」は退職を申し出る書類で、会社の承認を前提とします。受理前であれば撤回可能です。「退職届」は退職の意思を確定的に通知する書類で、提出後の撤回は原則として会社の同意が必要です。意思を強く伝える場合や証拠を残したい場合は退職届が適しています。
退職後、健康保険はどうすればいいですか?
+
退職後は健康保険の切替が必要です。主な選択肢は3つあります。①国民健康保険への加入(退職翌日から14日以内に市区町村窓口)、②任意継続被保険者(退職後20日以内に元の健保組合へ申請・最大2年)、③家族の扶養に入る。保険料を比較して、最も有利な方法を選ぶことをお勧めします。
AI設定 — Gemini APIキー
Google AI StudioでAPIキーを取得し、入力してください。キーはブラウザのみに保存され、外部に送信されません。
未設定 ▶ Google AI Studio でキーを取得
AIチャット — 退職・労働法Q&A Gemini
退職手続き・労働基準法に関するご質問にお答えします。一般的な情報提供であり、個別の法律相談ではありません。
こんにちは。退職手続き・労働法に関するご質問にお答えします。APIキーを設定すると、Gemini AIによる詳しい回答が利用できます。
完了した手続き
0 / 7 項目
手続き完了率
0%
退職後の必須手続きチェックリスト
各手続きが完了したらチェックを入れてください。期限のある手続きはお早めに。
  • 健康保険の切替(国保加入 or 任意継続)
    退職日の翌日から14日以内 · 市区町村窓口 または 元の健保組合
    期限あり
  • 国民年金への切替
    退職日の翌日から14日以内 · 市区町村窓口
    期限あり
  • ハローワークで失業給付の申請
    離職票受取後すみやかに · 管轄のハローワーク(住所地)
    重要
  • 住民税の支払い確認
    退職後は普通徴収(自分で納付)に切替わる。納付書が届いたら忘れずに。
    重要
  • 確定申告の準備(源泉徴収票の保管)
    年度内に再就職しない場合、翌年2〜3月に確定申告が必要。税金の還付が受けられる場合も。
    任意
  • 会社の備品・IDカードの返却
    PC・携帯・制服・社員証など。最終出社日に漏れなく返却する。
    確認
  • 社内システム・アカウントの整理
    個人情報・私用データの削除確認。社用メールからの私的データ除去。
    確認
退職後の相談窓口
  • 総合労働相談コーナー(各都道府県労働局)
    労働問題全般を無料でワンストップ相談。予約不要で利用可能。
  • 労働基準監督署
    未払い残業代・書類未発行など労働基準法違反の申告窓口。
  • ハローワーク(公共職業安定所)
    失業給付申請・離職票問題・求職活動の支援。
  • 法テラス(日本司法支援センター)
    収入に応じた法律相談・弁護士費用の立替え制度あり。
あなたの気持ちに、寄り添います
「やめたい」「でも迷っている」——どちらの気持ちも大切です。
このチャットは、あなたの話をじっくり聞き、自分の答えを見つけるお手伝いをします。
判断を急かしません。正解を押しつけません。ただ、一緒に考えます。
今の気持ちを教えてください
😤
もう辞めたい
気持ちははっきりしている
😔
辞めるか迷っている
どうすればいいか分からない
😮‍💨
疲れてしまった
心や体が限界に近い
😰
辞めた後が不安
踏み出すのが怖い
退職相談チャット Claude AI
気持ちを選ぶと、あなたに合った対話が始まります。何でも自由に話しかけてください。
こんにちは。今日はどんな気持ちでここに来ましたか?
上のボタンを選んでもいいですし、そのまま言葉で話しかけてもらっても構いません。
※ このチャットはAIによる情報提供・感情サポートです。心身に深刻な不調がある場合は、医療機関や産業カウンセラーへのご相談もご検討ください。
// ========== TAB NAVIGATION ========== const ALL_TABS = ['delivery','docs','simulator','faq','checklist','counsel']; function switchTab(id, btn) { ALL_TABS.forEach(t => document.getElementById('panel-' + t).classList.remove('active')); document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); document.getElementById('panel-' + id).classList.add('active'); btn.classList.add('active'); if (id === 'simulator') runSimulator(); } // ========== DELIVERY TAB ========== function selectMethod(el, type) { document.querySelectorAll('.method-card').forEach(c => c.classList.remove('active')); el.classList.add('active'); document.getElementById('method-email').style.display = type === 'email' ? 'block' : 'none'; document.getElementById('method-voice').style.display = type === 'voice' ? 'block' : 'none'; document.getElementById('method-pdf').style.display = type === 'pdf' ? 'block' : 'none'; } function scheduleEmail() { const dt = document.getElementById('send-datetime').value; const to = document.getElementById('to-email').value; if (!dt) { alert('送信日時を入力してください。'); return; } if (!to) { alert('送信先メールアドレスを入力してください。'); return; } const d = new Date(dt); const str = d.toLocaleDateString('ja-JP', {year:'numeric',month:'long',day:'numeric',weekday:'short'}) + ' ' + d.toLocaleTimeString('ja-JP', {hour:'2-digit', minute:'2-digit'}); document.getElementById('schedule-time-disp').textContent = str; document.getElementById('schedule-confirm').style.display = 'block'; updateProgress(40); } function generateEmailBody() { const body = document.getElementById('email-body'); body.value = `〇〇 部長 お世話になっております。△△部 山田太郎でございます。 誠に恐れ入りますが、一身上の都合により、令和〇年〇月〇日をもちまして退職いたしたく、 ここに謹んでご通知申し上げます。 退職届につきましては別途書面にてご提出いたします。 有給休暇の残日数につきましては、退職日までに消化させていただきたく存じます。 引継ぎ等については、誠意をもって対応いたします。 急なご連絡となり、大変ご迷惑をおかけいたします。 改めてご面談の機会をいただけますと幸いです。 何卒よろしくお願い申し上げます。 山田 太郎`; } // ========== DOCS TAB ========== let selectedDocType = 1; function selectDocType(n) { selectedDocType = n; [1,2,3].forEach(i => { document.getElementById('doctype-btn-' + i).className = 'btn' + (i === n ? ' btn-primary' : ''); }); } function generateDoc() { const name = document.getElementById('d-name').value.trim() || '山田 太郎'; const company = document.getElementById('d-company').value.trim() || '株式会社〇〇'; const dept = document.getElementById('d-dept').value.trim() || '△△部'; const addr = document.getElementById('d-address').value.trim() || '〒000-0000 〇〇県〇〇市〇〇町1-1-1'; const reason = document.getElementById('d-reason').value; const dateVal = document.getElementById('d-date').value; const dateStr = dateVal ? new Date(dateVal).toLocaleDateString('ja-JP',{year:'numeric',month:'long',day:'numeric'}) : '令和〇年〇月〇日'; const today = new Date().toLocaleDateString('ja-JP',{year:'numeric',month:'long',day:'numeric'}); const badge = document.getElementById('doc-type-badge'); let html = ''; if (selectedDocType === 1) { badge.textContent = '退職届'; html = `

${today}

退 職 届

 この度、${reason}により、${dateStr}をもちまして退職いたしたく、ここにお届け申し上げます。



所 属:${company} ${dept}
氏 名:${name}    ㊞



${company}
代表取締役 〇〇 〇〇 殿

`; } else if (selectedDocType === 2) { badge.textContent = '書類一括請求書'; html = `

${today}

書類交付請求書

${company}
人事部 御中


 下記の書類を交付いただきますよう、謹んでお願い申し上げます。



1.雇用保険被保険者離職票(第1号・第2号)
2.雇用保険被保険者証
3.源泉徴収票(退職年分)
4.健康保険・厚生年金保険資格喪失確認通知書


以上


所 属:${dept}
氏 名:${name}    ㊞
送付先:${addr}

`; } else { badge.textContent = '源泉徴収票請求'; html = `

${today}

源泉徴収票 交付請求書

${company}
人事部 御中


 所得税法第226条の規定に基づき、下記のとおり源泉徴収票の交付をお願い申し上げます。



・退職年月日:${dateStr}
・氏  名:${name}
・所属(退職時):${dept}


 ご多忙のところ大変恐れ入りますが、下記住所宛にご郵送いただけますと幸いです。

送付先住所:${addr}


氏 名:${name}    ㊞

`; } document.getElementById('doc-preview-content').innerHTML = html; document.getElementById('doc-preview-area').style.display = 'block'; document.getElementById('doc-preview-area').scrollIntoView({behavior:'smooth', block:'start'}); updateProgress(60); } function printDoc() { const content = document.getElementById('doc-preview-content').innerHTML; const w = window.open('', '_blank'); w.document.write(` 書類出力 ${content}`); w.document.close(); setTimeout(() => w.print(), 300); } function copyDocText() { const txt = document.getElementById('doc-preview-content').innerText; navigator.clipboard.writeText(txt).then(() => alert('書類テキストをクリップボードにコピーしました。')); } function clearDocForm() { ['d-name','d-empno','d-company','d-dept','d-address'].forEach(id => document.getElementById(id).value = ''); document.getElementById('d-date').value = ''; } // ========== SIMULATOR ========== function fmt10k(n) { return Math.round(n / 10000) + '万円'; } function drawCashflowChart(balances, waitMonths) { const svgEl = document.getElementById('cf-chart'); if (!svgEl) return; const W = 800, H = 200; const pad = { top: 22, right: 18, bottom: 30, left: 64 }; const iW = W - pad.left - pad.right; const iH = H - pad.top - pad.bottom; const maxB = Math.max(...balances, 0); const minB = Math.min(...balances, 0); const span = (maxB - minB) || 1; const xS = i => pad.left + (i / (balances.length - 1)) * iW; const yS = v => pad.top + iH - ((v - minB) / span) * iH; const zeroY = yS(0); const labels = ['退職時','1ヶ月後','2ヶ月後','3ヶ月後','4ヶ月後','5ヶ月後']; let out = ``; // Grid lines [0.25, 0.5, 0.75, 1.0].forEach(frac => { const v = minB + span * frac; const y = yS(v); if (y > pad.top && y < pad.top + iH) { out += ``; const label = Math.round(v / 10000) + '万'; out += `${label}`; } }); // Zero line out += ``; // Benefit period shading const benefitStart = waitMonths; const benefitEnd = Math.min(5, waitMonths + 3); if (benefitStart <= 5) { const x1 = xS(benefitStart), x2 = xS(Math.min(benefitEnd, 5)); out += ``; out += `失業手当給付期間`; } // Area let areaPath = `M${xS(0).toFixed(1)},${zeroY.toFixed(1)} L${xS(0).toFixed(1)},${yS(balances[0]).toFixed(1)}`; for (let i = 1; i < balances.length; i++) { areaPath += ` L${xS(i).toFixed(1)},${yS(balances[i]).toFixed(1)}`; } areaPath += ` L${xS(balances.length-1).toFixed(1)},${zeroY.toFixed(1)} Z`; out += ``; // Line let linePath = `M${xS(0).toFixed(1)},${yS(balances[0]).toFixed(1)}`; for (let i = 1; i < balances.length; i++) { linePath += ` L${xS(i).toFixed(1)},${yS(balances[i]).toFixed(1)}`; } out += ``; // Negative area const negBalances = balances.map(b => Math.min(b, 0)); if (negBalances.some(b => b < 0)) { let negPath = `M${xS(0).toFixed(1)},${zeroY.toFixed(1)} L${xS(0).toFixed(1)},${yS(negBalances[0]).toFixed(1)}`; for (let i = 1; i < balances.length; i++) { negPath += ` L${xS(i).toFixed(1)},${yS(negBalances[i]).toFixed(1)}`; } negPath += ` L${xS(balances.length-1).toFixed(1)},${zeroY.toFixed(1)} Z`; out += ``; } // Points + labels balances.forEach((b, i) => { const x = xS(i), y = yS(b); const col = b >= 0 ? '#1D9E75' : '#A32D2D'; out += ``; const lbl = Math.round(b/10000) + '万'; const labelY = b >= 0 ? y - 9 : y + 16; out += `${lbl}`; out += `${labels[i]}`; }); svgEl.setAttribute('viewBox', `0 0 ${W} ${H}`); svgEl.setAttribute('preserveAspectRatio', 'xMidYMid meet'); svgEl.innerHTML = out; } // ========== FAQ ========== function toggleFaq(el) { const ans = el.nextElementSibling; const isOpen = ans.classList.contains('open'); document.querySelectorAll('.faq-a').forEach(a => a.classList.remove('open')); document.querySelectorAll('.faq-icon').forEach(ic => ic.textContent = '+'); if (!isOpen) { ans.classList.add('open'); el.querySelector('.faq-icon').textContent = '−'; } } // ========== API KEY ========== function saveApiKey() { const key = document.getElementById('gemini-api-key').value.trim(); if (key) { localStorage.setItem('gemini_api_key', key); document.getElementById('api-status-badge').className = 'badge badge-green'; document.getElementById('api-status-badge').textContent = '設定済み ✓'; } else { localStorage.removeItem('gemini_api_key'); document.getElementById('api-status-badge').className = 'badge badge-warn'; document.getElementById('api-status-badge').textContent = '未設定'; } } function toggleApiKeyVisibility() { const inp = document.getElementById('gemini-api-key'); const btn = document.getElementById('toggle-key-btn'); if (inp.type === 'password') { inp.type = 'text'; btn.textContent = '隠す'; } else { inp.type = 'password'; btn.textContent = '表示'; } } function loadApiKey() { const saved = localStorage.getItem('gemini_api_key'); if (saved) { document.getElementById('gemini-api-key').value = saved; document.getElementById('api-status-badge').className = 'badge badge-green'; document.getElementById('api-status-badge').textContent = '設定済み ✓'; } } // ========== CHAT ========== const SYSTEM_PROMPT = `あなたは日本の退職手続き・労働法の専門アシスタントです。 以下のルールを守って回答してください: - 退職手続き、労働基準法、雇用保険、健康保険、年金など退職に関連するトピックに特化して回答する - 回答は簡潔で分かりやすい日本語にする - 法的な根拠(民法、労働基準法等)がある場合は条文番号を示す - 個別の法律相談ではなく一般的な情報提供であることを必要に応じて付記する - 窓口(ハローワーク、労基署等)を適切に案内する`; const chatHistory = []; async function sendChat() { const inp = document.getElementById('chat-input'); const q = inp.value.trim(); if (!q) return; const apiKey = localStorage.getItem('gemini_api_key') || ''; appendMsg(q, 'user'); inp.value = ''; inp.disabled = true; document.getElementById('send-btn').disabled = true; if (!apiKey) { appendMsg('⚠ APIキーが設定されていません。上の「AI設定」カードでGemini APIキーを入力してください。', 'bot'); inp.disabled = false; document.getElementById('send-btn').disabled = false; return; } const typingId = 'typing-' + Date.now(); appendTyping(typingId); chatHistory.push({ role: 'user', parts: [{ text: q }] }); try { const res = await fetch( `https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ system_instruction: { parts: [{ text: SYSTEM_PROMPT }] }, contents: chatHistory, generationConfig: { maxOutputTokens: 800, temperature: 0.7 } }) } ); const data = await res.json(); removeTyping(typingId); if (data.error) { const errMsg = data.error.message || 'APIエラーが発生しました。'; appendMsg('⚠ ' + errMsg, 'bot'); chatHistory.pop(); } else { const reply = data.candidates?.[0]?.content?.parts?.[0]?.text || '回答を取得できませんでした。'; chatHistory.push({ role: 'model', parts: [{ text: reply }] }); appendMsg(reply, 'bot'); } } catch (e) { removeTyping(typingId); appendMsg('⚠ 通信エラーが発生しました。ネットワーク接続とAPIキーをご確認ください。', 'bot'); chatHistory.pop(); } finally { inp.disabled = false; document.getElementById('send-btn').disabled = false; inp.focus(); } } function appendTyping(id) { const box = document.getElementById('chat-msgs'); const d = document.createElement('div'); d.className = 'msg bot'; d.id = id; d.innerHTML = '入力中…'; box.appendChild(d); box.scrollTop = box.scrollHeight; } function removeTyping(id) { const el = document.getElementById(id); if (el) el.remove(); } function appendMsg(text, role) { const box = document.getElementById('chat-msgs'); const d = document.createElement('div'); d.className = 'msg ' + role; d.textContent = text; box.appendChild(d); box.scrollTop = box.scrollHeight; } // ========== CHECKLIST ========== function updateChecklist() { const items = document.querySelectorAll('#cl-list li'); const total = items.length; let done = 0; items.forEach(li => { const checked = li.querySelector('input[type=checkbox]').checked; li.classList.toggle('done', checked); if (checked) done++; }); document.getElementById('cl-done-count').textContent = done + ' / ' + total + ' 項目'; document.getElementById('cl-pct').textContent = Math.round(done / total * 100) + '%'; updateProgress(20 + Math.round(done / total * 60)); } function updateProgress(pct) { document.getElementById('progress-fill').style.width = Math.min(pct, 100) + '%'; document.getElementById('progress-label').textContent = '全体進捗:' + Math.min(pct, 100) + '%'; } // ========== INIT ========== runSimulator(); loadApiKey(); // ========== SIMULATOR AI ========== let lastSimData = {}; function runSimulator() { const income = +document.getElementById('sim-income').value; const savings = +document.getElementById('sim-savings').value; const paid = +document.getElementById('sim-paid').value; const expense = +document.getElementById('sim-expense').value; const years = +document.getElementById('sim-years').value; const type = document.getElementById('sim-type').value; lastSimData = { income, savings, paid, expense, years, type }; document.getElementById('disp-income').textContent = fmt10k(income); document.getElementById('disp-savings').textContent = fmt10k(savings); document.getElementById('disp-paid').textContent = paid + '日'; document.getElementById('disp-expense').textContent = fmt10k(expense); document.getElementById('disp-years').textContent = years + '年'; const dailyWage = income / 22; const paidIncome = dailyWage * paid; const wageDaily = (income * 12) / 365; const benefitRate = wageDaily > 13000 ? 0.50 : wageDaily > 5000 ? 0.65 : 0.80; const dailyBenefit = wageDaily * benefitRate; const monthlyBenefit = dailyBenefit * 28; let giveDays = 90; if (type === 'involuntary') { giveDays = years < 1 ? 90 : years < 5 ? 90 : years < 10 ? 120 : years < 20 ? 180 : 240; } else { giveDays = years < 1 ? 90 : years < 10 ? 90 : years < 20 ? 120 : 150; } const giveMonths = Math.ceil(giveDays / 30); const waitMonths = type === 'voluntary' ? 2 : 0; const balances = []; let cash = savings + paidIncome; for (let m = 0; m <= 5; m++) { balances.push(Math.round(cash)); const inBenefitPeriod = m >= waitMonths && m < waitMonths + giveMonths; if (inBenefitPeriod) cash += monthlyBenefit; cash -= expense; } document.getElementById('m-paid').textContent = fmt10k(paidIncome); document.getElementById('m-benefit').textContent = fmt10k(monthlyBenefit); const firstNeg = balances.findIndex(b => b < 0); const safeEl = document.getElementById('m-safe'); if (firstNeg < 0) { safeEl.textContent = '6ヶ月以上'; safeEl.className = 'metric-value green'; } else if (firstNeg <= 2) { safeEl.textContent = firstNeg + 'ヶ月'; safeEl.className = 'metric-value danger'; } else { safeEl.textContent = firstNeg + 'ヶ月'; safeEl.className = 'metric-value warn'; } const alertBox = document.getElementById('sim-alert-box'); if (firstNeg < 0) { alertBox.innerHTML = `
✓ 6ヶ月間、収支は黒字の見込みです。安心して手続きを進められます。
`; } else if (firstNeg <= 2) { alertBox.innerHTML = `
⚠ 退職後 ${firstNeg}ヶ月で資金不足の見込みです。生活費の見直しや早期の再就職活動をご検討ください。
`; } else { alertBox.innerHTML = `
△ 退職後 ${firstNeg}ヶ月以降で資金が減少する見込みです。計画的に再就職活動を進めましょう。
`; } lastSimData.paidIncome = paidIncome; lastSimData.monthlyBenefit = monthlyBenefit; lastSimData.firstNeg = firstNeg; lastSimData.waitMonths = waitMonths; lastSimData.giveMonths = giveMonths; drawCashflowChart(balances, waitMonths); } async function runSimAI() { const btn = document.getElementById('sim-ai-btn'); const resultBox = document.getElementById('sim-ai-result'); const loadingEl = document.getElementById('sim-ai-loading'); const textEl = document.getElementById('sim-ai-text'); btn.disabled = true; resultBox.style.display = 'block'; loadingEl.style.display = 'block'; textEl.style.display = 'none'; const d = lastSimData; const typeLabel = d.type === 'voluntary' ? '自己都合退職' : '会社都合退職'; const safeLabel = d.firstNeg < 0 ? '6ヶ月以上' : d.firstNeg + 'ヶ月'; const prompt = `あなたは退職・キャリア・家計の専門アドバイザーです。以下のシミュレーション結果をもとに、この方への具体的で温かみのあるアドバイスを日本語で提供してください。 【シミュレーション条件】 - 退職種別:${typeLabel} - 月収(手取り):${Math.round(d.income/10000)}万円 - 現在の貯蓄:${Math.round(d.savings/10000)}万円 - 有給残日数:${d.paid}日 - 月間生活費:${Math.round(d.expense/10000)}万円 - 勤続年数:${d.years}年 【計算結果】 - 有給消化収入:${Math.round(d.paidIncome/10000)}万円 - 失業手当(月額概算):${Math.round(d.monthlyBenefit/10000)}万円 - 給付制限期間:${d.waitMonths}ヶ月 - 資金が続く見込み:${safeLabel} 以下の観点でアドバイスしてください(合計400〜500文字程度): 1. 財務状況の評価(ポジティブな点・注意点) 2. 退職直後〜3ヶ月の具体的な資金管理のアドバイス 3. 失業手当受給に向けた準備のポイント 4. 前向きな一言 数字を引用しながら、この方の具体的な状況に寄り添った内容にしてください。`; try { const response = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'claude-sonnet-4-20250514', max_tokens: 1000, messages: [{ role: 'user', content: prompt }] }) }); const data = await response.json(); loadingEl.style.display = 'none'; textEl.style.display = 'block'; const reply = data.content?.[0]?.text || 'アドバイスを取得できませんでした。'; textEl.textContent = reply; } catch(e) { loadingEl.style.display = 'none'; textEl.style.display = 'block'; textEl.textContent = '⚠ エラーが発生しました。しばらくしてからもう一度お試しください。'; } finally { btn.disabled = false; } } // ========== COUNSEL CHAT ========== let counselHistory = []; let counselMood = null; const MOOD_LABELS = { quit: 'もう辞めたいという気持ちがはっきりしている', unsure: '辞めるか迷っている・どうすればいいか分からない', tired: '心や体が疲れてしまった・限界に近い', scared: '辞めた後の生活や将来が不安で踏み出せない' }; const COUNSEL_SYSTEM = `あなたは、退職を考えている人に寄り添う共感的なカウンセラーです。 以下のスタンスで対話してください: 【基本姿勢】 - 「辞めるべき」「辞めるな」という結論を押しつけない - 相手の気持ちをまず受け止め、共感から始める - 質問を通じて相手が自分の気持ちを整理できるようサポートする - 「正解」を教えるのではなく、相手自身が答えを見つけるのを助ける - 温かく、丁寧な日本語を使う 【対話の流れ】 1. まず共感・受容(「それは辛かったですね」など) 2. 状況や気持ちをもう少し聞く(1〜2つの質問) 3. 相手のペースで深掘りしていく 4. 必要に応じて、具体的な選択肢や視点を提供する 【禁止事項】 - 「辞めましょう」「続けましょう」という直接的な結論 - 批判や否定 - 長すぎる回答(200文字以内を目安に) 回答は200文字以内の温かい日本語で。`; function selectMood(el, mood) { document.querySelectorAll('.mood-btn').forEach(b => b.classList.remove('active')); el.classList.add('active'); counselMood = mood; counselHistory = []; const moodText = MOOD_LABELS[mood]; const msgBox = document.getElementById('counsel-msgs'); msgBox.innerHTML = ''; const openingMessages = { quit: 'そうですか、辞めたいという気持ちがはっきりあるんですね。\nその気持ち、ちゃんと受け止めています。\n\nよければ、どんなことがきっかけでそう思うようになったか、少し聞かせてもらえますか?', unsure: '辞めるかどうか迷っているんですね。\nどちらに進んでも不安があって、決められない状態、それだけで疲れますよね。\n\n今、一番引っかかっていることは何でしょうか?', tired: '心や体が限界に近いんですね。\nそこまで頑張ってきたこと、本当に大変だったと思います。\n\n今、一番つらいのはどんなことですか?無理のない範囲で話してください。', scared: '辞めた後のことが不安で、踏み出せないんですね。\nその不安、とても自然な気持ちだと思います。\n\n具体的にどんなことが心配ですか?お金のこと、仕事のこと、それとも別のことでしょうか?' }; appendCounselMsg(openingMessages[mood], 'bot'); counselHistory.push({ role: 'user', content: `私の今の状況:${moodText}` }); counselHistory.push({ role: 'assistant', content: openingMessages[mood] }); } async function sendCounsel() { const inp = document.getElementById('counsel-input'); const q = inp.value.trim(); if (!q) return; appendCounselMsg(q, 'user'); inp.value = ''; inp.disabled = true; document.getElementById('counsel-send-btn').disabled = true; const typingId = 'ctyping-' + Date.now(); appendCounselTyping(typingId); counselHistory.push({ role: 'user', content: q }); if (!counselMood) { counselHistory.push({ role: 'user', content: '(気持ちの選択なしで相談開始)' }); } try { const response = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'claude-sonnet-4-20250514', max_tokens: 1000, system: COUNSEL_SYSTEM, messages: counselHistory }) }); const data = await response.json(); removeCounselTyping(typingId); const reply = data.content?.[0]?.text || '申し訳ありません、うまく受信できませんでした。もう一度話しかけてみてください。'; counselHistory.push({ role: 'assistant', content: reply }); appendCounselMsg(reply, 'bot'); } catch(e) { removeCounselTyping(typingId); appendCounselMsg('⚠ 通信エラーが発生しました。しばらくしてから再度お試しください。', 'bot'); counselHistory.pop(); } finally { inp.disabled = false; document.getElementById('counsel-send-btn').disabled = false; inp.focus(); } } function appendCounselMsg(text, role) { const box = document.getElementById('counsel-msgs'); const d = document.createElement('div'); d.className = 'msg ' + role; if (role === 'bot') { d.style.cssText = 'white-space:pre-wrap;'; } d.textContent = text; box.appendChild(d); box.scrollTop = box.scrollHeight; } function appendCounselTyping(id) { const box = document.getElementById('counsel-msgs'); const d = document.createElement('div'); d.className = 'msg bot'; d.id = id; d.innerHTML = '考えています…'; box.appendChild(d); box.scrollTop = box.scrollHeight; } function removeCounselTyping(id) { const el = document.getElementById(id); if (el) el.remove(); }