import React, { useState, useEffect, useMemo } from 'react'; import { ChevronRight, ChevronLeft, User, Users, Target, MessagesSquare, RefreshCcw, BrainCircuit, Loader2, Printer, CheckCircle2, GraduationCap, Award, TrendingUp, Info } from 'lucide-react'; import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, ResponsiveContainer, Tooltip } from 'recharts'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, collection, addDoc, serverTimestamp } from 'firebase/firestore'; // --- CONFIG --- const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'jobee-assessment-v1'; // 【重要】ご自身のGASウェブアプリURLをここに貼り付けてください const GAS_WEBAPP_URL = "https://script.google.com/macros/s/AKfycbw3QGrejHe_DhDFdOEDFlfMrM_SCE-G8JN0QfpxhBN5pCOZLzxx3q5ln5eBW9_2L5O6/exec"; const PROFESSIONS = ["IT・通信", "金融・保険", "製造・メーカー", "サービス・飲食", "不動産・建設", "医療・福祉", "公務員・教育", "学生", "自営業", "その他"]; // --- 因子と解説の定義 --- const CAT_CONFIG = { self: { name: '自分と向き合う力', color: '#6366f1', summary: '内面循環(振り返り・認識・受容)の強さを示します。', factors: { A: { name: '内省習慣', high: '日常の出来事をそのまま流さず、自分の判断を自然に振り返る習慣があります。成長が積み上がる構造を持っています。', mid: '振り返る力を既に備えており、適切に活用できています。安定感を増すことで、経験をさらに大きな成長へと変える高いポテンシャルを秘めています。', low: '出来事を処理することに意識が向きやすく、立ち止まる時間が少ない状態です。思考の癖を掘り下げる練習が効果的です。', adv: '「振り返りの型」を固定化するとさらに成長が加速します。', train: '1日1回、「今日いちばん迷った判断」を1行書き出すことから始めてください。' }, B: { name: '感情認識', high: '自分の感情の動きを自覚し、言葉で整理できます。判断の背景にある心理状態を理解できる成熟度が高い状態です。', mid: '自分の感情の変化に敏感であり、冷静に心の動きを捉えることができています。強い感情が動く場面でもこの客観性を維持できるようになれば、対人スキルはさらに向上します。', low: '自分の感情を自覚する前に反応してしまうことが多い状態です。まず感情に名前をつけることが第一歩です。', adv: '感情のメッセージを読み取りましょう。その感情は何を守りたいのか問い直してください。', train: '1日の終わりに「今日感じた感情を3つ」単語で書き出してください。' }, C: { name: '他責回避', high: '環境や他者だけに原因を求めず、「自分にできたことは何か」を冷静に探せる状態です。具体的改善が可能になり成長が持続します。', mid: '責任感があり、主体的に改善を試みることができています。自分に何ができるかを考える姿勢は周囲の信頼に繋がっています。複雑な状況でもこの視点を維持することで飛躍が期待できます。', low: '問題の原因を外部に置きやすく、自分の影響可能性を見落としやすい状態です。影響可能な範囲を見つける意識が必要です。', adv: '影響可能/不能の切り分けを明確にしましょう。具体的行動に落とす習慣を持つと精度が上がります。', train: '「自分が変えられた点を1つだけ書く」練習をしてください。責任ではなく改善可能性です。' }, D: { name: '自己受容', high: '弱みや未熟さを認識しても自己否定に直結させない安定感があります。失敗と自己価値を切り離して扱うため、再挑戦がしやすい強みを持っています。', mid: '自分の長所と短所を理解し、等身大の自分を受け入れる土台があります。この自己肯定感を維持しつつ、さらに自分の「伸び代」を愛することができれば挑戦の幅が広がります。', low: '失敗や指摘が自己否定に直結しやすく、引きずってしまう傾向があります。できない自分を受け入れ、成長の出発点に変えましょう。', adv: '挑戦領域を意図的に広げてください。弱さを適度な「開示」に変えると周囲の安心感も高まります。', train: '失敗した時、「できなかったこと」と同時に「できたこと」を必ずセットで挙げましょう。' }, E: { name: '学習転換', high: '困難や失敗を意味づけし、次の行動へ転換できる状態です。挫折を資源として扱える、長期的成長の基盤があります。', mid: '経験から教訓を導き出す力を持っており、過去の成功や失敗を無駄にせず活かそうとする意欲があります。このプロセスを日常のルーチンに組み込むことで学習速度は加速します。', low: '失敗を振り返ることを避けやすい状態です。完璧な分析ではなく、小さな行動修正に変換する回路を育てましょう。', adv: '「教訓→原則→次の実験」の3段階で整理してください。経験を言語化し、再現可能なルールに落とし込みましょう。', train: '失敗から「次にやらないこと」を1つ決めるだけで十分です。小さな行動修正が前進を生みます。' } } }, others: { name: '他者と向き合う力', color: '#10b981', summary: '対人関係の構築力(傾聴・共感・視点移動)を示します。', factors: { A: { name: '傾聴姿勢', high: '相手の話を遮らずに聴くことが自然にできます。対話の土台が非常に安定しており、チームに心理的安全性を与えています。', mid: '相手の話を尊重し、真摯に耳を傾ける姿勢を大切にしています。相手の言葉の要点を受け取る力があり、基本的な信頼関係を構築できています。多忙な場面でもこれを維持できれば対話の質はさらに高まります。', low: '聴く前に反論が浮かびやすく、遮ってしまうことがあります。聴くことを優先する意識転換が必要です。', adv: '「要約確認」を取り入れると精度が上がります。「つまり◯◯ですね」と確認しましょう。', train: '1日1回、最後まで遮らずに聴き、最後に一文で要約する練習をしてください。' }, B: { name: '視点移動', high: '自分と異なる意見に出会っても否定せず、背景を想像できます。多様性を前提とした対話が可能になります。', mid: '他者の立場や事情を考慮する柔軟性を持っています。異なる意見にも「理由がある」と理解しようとする健全な意識があります。視点を切り替えるスピードを意識的に早めることで影響力が強まります。', low: '自分の価値観を中心に判断しやすく、対話が平行線になりやすいです。視点を広げる練習が必要です。', adv: '対立場面で「双方の利害」を言語化してください。守りたい価値を整理すると、創造的な調整力が身につきます。', train: '意見が合わない時、「もし自分がその立場なら?」と必ず自問してください。相手の制約を想像するだけで十分です。' }, C: { name: '判断保留', high: '第一印象で結論を出さず、文脈を探ろうとする姿勢が安定しています。誤解を防ぎ、信頼関係を維持しやすい強みを持っています。', mid: '客観的な視点を持ち、他者を性急に決めつけないよう努めることができています。情報の背景を確認しようとする誠実な姿勢があります。この丁寧なプロセスを続けることで、より精度の高い判断が可能になります。', low: '相手を短時間で評価しがちです。事実と解釈が混ざりやすいため、思考のスピードを緩める練習が必要です。', adv: '「結論ではなく仮説として置く」意識を強め、周囲に「他の可能性は?」と問いを投げる役割を担ってください。', train: '何かを感じたら「それは事実か、解釈か」と自問しましょう。出来事を分けて書くことが効果的です。' }, D: { name: '役割理解', high: '職種や立場の違いを尊重し、制約を理解しようとします。対立を個人化せず構造的に捉えられるため、合意形成がスムーズです。', mid: '組織内での各役割の意義を理解し、異なる職種の人々の判断を尊重する姿勢を持っています。全体の「守るべきもの」にまで想像を広げると、合意形成力が一段高まります。', low: '自分の価値基準を他者に適用しやすく、立場の違いを考慮できていない状態です。役割という視点を持ちましょう。', adv: '立場別の視点整理を担ってみてください。構造化する力を発揮することで、議論が前進します。', train: '対立相手の「責任範囲」を紙に書き出してみてください。個人ではなく役割としての構造を捉える練習です。' }, E: { name: '関係配慮', high: '言葉選びや伝え方に配慮し、対立場面でも関係を損なわずに主張できます。安心と挑戦を両立できる貴重な力を持っています。', mid: '良好な人間関係を維持するための丁寧な配慮ができています。周囲から「接しやすい」と感じられています。この力をベースに、あえて率直に意見を述べる技術を磨くことで、真の共創が可能になります。', low: '正しさや結論を優先し、配慮が後回しになりやすいです。自分では合理的なつもりでも攻撃的に伝わることがあるため注意が必要です。', adv: '「率直さ」を少し足すと影響力が高まります。「私はこう感じている」と私を主語にしたメッセージを活用しましょう。', train: '指摘の前に、必ず相手の努力を1つ認める習慣を持ちましょう。' } } }, achievement: { name: '自己実現に向かう力', color: '#f59e0b', summary: '推進力と持続力(動機・成長・粘り強さ)を示します。', factors: { A: { name: '内発動機', high: '「自分が納得できるか」を行動の起点にできます。目的と行動が結びついているため、困難があってもブレにくい状態です。', mid: '仕事の目的や価値を主体的に捉えようとする健全な意欲があります。自分が納得して動くことの重要性を理解しており、意味が見える課題には高い集中力を発揮します。価値観をより明確にすることで意欲はさらに安定します。', low: '評価にエネルギーが寄りやすく、目的が見えないと継続力が落ちます。小さな意味づけが必要です。', adv: '譲れない価値を3つに絞り、意思決定基準として使ってください。', train: '今の仕事が誰の役に立っているか3つ書き出す「意味づけ実験」をしてください。' }, B: { name: '成長志向', high: 'できないことを「伸びしろ」として扱えます。学びの好循環が回りやすく、難易度の高い挑戦にも踏み込むことができます。', mid: '自己研鑽への関心が高く、新しいことを学ぶことに積極的な姿勢を持っています。失敗を「学びの過程」と捉えるポジティブさがあり、着実に前進できています。独自の成長指標を持つことで、喜びはさらに強まります。', low: '能力は固定と考えやすく、変化を避けがちです。失敗を人格から切り離し方法を修正する視点が必要です。', adv: '挑戦テーマに学びたいスキル、検証方法をセットで設計すると成長が再現性を持ちます。', train: '「昨日より1ミリできたこと」を毎日1行書いて可視化してください。' }, C: { name: '粘り強さ', high: '困難な状況でも工夫を重ねながら継続できます。感情が揺れても立て直しが早く、周囲から厚い信頼を得やすいです。', mid: '責任感が強く、目標に対して地道に取り組む継続力を持っています。一定の負荷がかかる場面でも踏ん張ることができ、最後までやり遂げようとする意志があります。自分を「持続させる仕組み」を強化しましょう。', low: '困難が続くと止まりやすく「やっても無駄」と感じやすいです。短期の成功体験で自己効力感を回復させましょう。', adv: '目標を最小行動に分解し、停滞期に備えた補給(休息・相談)をあらかじめ予定に入れましょう。', train: '15分×3日の「最小挑戦」を繰り返し、連続実行そのものを評価してください。' }, D: { name: '強み活用', high: '自分の得意を理解し状況に応じて意識的に使えます。効率的で満足度も高く、自己効力感が自然に育つ状態です。', mid: '自分の得意分野を自覚し、活かそうとする意図的な努力ができています。強みを発揮した時の喜びを知っており、自分らしさを大切にできています。強みを「再現可能な型」にすることで、安定性は一段と高まります。', low: '強みが曖昧で弱み改善に意識が偏っています。外部視点を取り入れて強みの特定が先決です。', adv: '強みを発揮できた場面を選び、なぜうまくいったのか「条件」を整理してください。', train: '信頼できる3人に「自分の強み」を聞き、それを使える小さな場面を1日1個作りましょう。' }, E: { name: '挫折耐性', high: '失敗があっても自己否定に飲み込まれず回復できます。挫折を資源化して次へ活かせるため、修羅場に強いタイプです。', mid: '失敗した際に自分の気持ちを整え、再び前を向くための回復力を持っています。一時的に落ち込んでも自力で立ち上がる力があります。この回復プロセスをより迅速にすることで、揺るぎない自信を持つことができます。', low: '失敗が自己否定と結びつきやすく、挑戦を避けがちです。まず自分を責めない回復の手順を身につけましょう。', adv: '失敗を「教訓→原則」に変えるセルフ手順書を持ってください。他者支援にも活かせます。', train: '落ち込んだ時、感情・事実・最小行動の3ステップを24時間以内に行う型を作りましょう。' } } }, adaptive: { name: '適応課題を解決する力', color: '#a855f7', summary: '共創と対話の力(対立耐性・第三案創出)を示します。', factors: { A: { name: '対立耐性', high: '対立を「より良い解を生む過程」と捉えられます。論点に意識を向け続けられるため、組織の成熟度を高める役割を果たします。', mid: '意見の相違を前向きに捉えようとする誠実な姿勢があります。異なる主張がぶつかる場でも、逃げずに向き合おうとする勇気を持っています。対立を「違いの可視化」と捉え直すことで、さらに落ち着いて議論をリードできます。', low: '強い意見の対立をストレスと感じ避けがちです。対立を関係悪化と結びつけやすいため、捉え直しが必要です。', adv: '「この議論は答えを探すためのものです」と言語化し、場の安心感を高めてください。', train: '対立時に「相手は何を守ろうとしているか」書き出す練習をしましょう。' }, B: { name: '対話姿勢', high: '結論を急ぐよりプロセスに価値を見出せます。納得感のある決定を生み出し、長期的な実行力を高めます。', mid: '対話を通じて相互理解を深める価値を理解し、粘り強く話し合う姿勢を持っています。相手の意見を聞きながら自分の考えを修正する柔軟性もあります。「目的」を常に意識し続けることで合意の質はさらに向上します。', low: '迅速な決定を優先し、対話を非効率に感じがちです。対話が実行力の投資であるという認識が必要です。', adv: '議論の冒頭で目的を明確にし、発言の少ない人に問いを投げかけて場を広げてください。', train: '会議で一度「もう一度整理させてください」と発言し、議論を止めずに深める経験を積みましょう。' }, C: { name: '両立思考', high: '「AかBか」ではなく「AもBも満たすには」と考えられます。妥協ではない創造的統合を目指す思考を持っています。', mid: '二項対立のジレンマを理解し、共存の道を模索する意欲があります。多角的な視点を持って解決策を探る姿勢は貴重です。問いの立て方を工夫することで、さらに画期的な統合案を生み出せるようになります。', low: 'どちらかが折れるしかないと捉えがちです。二項対立に固定され不満を残す決定になりやすいです。', adv: '「両方守る条件は何か?」と問い続けてください。あえて相反する条件を同時に守るための「第3の条件」を探しましょう。', train: '対立する2意見のそれぞれの価値を書き出し、共通の目的を1つ探すトレーニングをしましょう。' }, D: { name: '第三案創出', high: '行き詰まりを「新しい可能性の入口」と捉えられます。チームに新しい視界を提示できる貴重な存在です。', mid: '既存のやり方にとらわれない柔軟な思考を持っており、新しい解決策を提案しようとするクリエイティビティがあります。前提条件を疑う習慣を強めることで、発想の独自性はさらに高まります。', low: '前例の中から答えを探す傾向が強く、変化への不安が創造性を抑えている可能性があります。', adv: '「前提は本当に固定か?」を疑う問いを習慣化してください。再現性のある思考を構築しましょう。', train: '意見が分かれたら、既存選択肢の「真逆」を一度考えてから案を出す訓練をしましょう。' }, E: { name: '合意形成', high: '納得して進めることを重視できます。全員の声を丁寧に扱うため決定後の実行力が高く、組織に安定感をもたらします。', mid: '関係者の納得感に配慮しながら議論をまとめ、着地させる力を持っています。プロセスを大切にする姿勢はスムーズな協力体制を築く力となります。判断基準を事前により明確化することで、スピードと質がさらに向上します。', low: '迅速さを優先し納得感が形成されにくいため、後で不満が出るリスクがあります。合意は投資だという認識が必要です。', adv: '判断基準を明確に言語化し、合意後に「なぜこの決定に至ったか」整理して組織の資産にしましょう。', train: '決定直前に「懸念が残っている人はいるか」必ず問い、不完全一致でも声を可視化してください。' } } } }; // --- 設問マスタ 160問 --- const QUESTIONS = [ ...[ "仕事が一区切りついたとき、自分の行動を振り返ることが多い", "うまくいかなかった出来事を、後から考え直す習慣がある", "結果よりも「なぜそうなったか」を考えることが多い", "忙しい時ほど、一度立ち止まって考えることを意識している", "同じ失敗を繰り返さないよう、原因を整理しようとする", "成功したときも、自分の判断や工夫を振り返る", "日々の出来事をそのまま流してしまうことが多い", "自分の行動を振り返る時間は、あまり必要ないと思う" ].map((t, i) => ({ id: i + 1, cat: 'self', factor: 'A', text: t, isRev: i >= 6 })), ...[ "自分が今どんな感情でいるかを、言葉で表せるほうだ", "モヤモヤした気持ちの正体を考えることがある", "イライラしているとき、その理由に気づけることが多い", "感情が仕事の判断に影響していると感じることがある", "気分が落ち込んだとき、その原因を整理しようとする", "自分の感情に気づかないまま行動してしまうことが多い", "感情はあまり意識せず、行動するタイプだと思う", "自分の感情を後回しにしてしまうことが多い" ].map((t, i) => ({ id: i + 9, cat: 'self', factor: 'B', text: t, isRev: i >= 5 })), ...[ "失敗したとき、まず自分にできたことは何かを考える", "環境や他人のせいにしたくなる場面でも、自分の行動を振り返る", "思い通りにいかない結果にも、自分なりの原因があると感じる", "指摘を受けたとき、感情的にならず受け止めようとする", "反省点を次の行動に活かそうとする", "うまくいかなかった理由を外部要因だけで説明することが多い", "自分は悪くないと思うことがよくある", "失敗したとき、まず言い訳を考えてしまう" ].map((t, i) => ({ id: i + 17, cat: 'self', factor: 'C', text: t, isRev: i >= 5 })), ...[ "自分の弱みや苦手なことを認められるほうだ", "完璧でなくても仕方ないと思える", "他人と比べて落ち込んでも、自分を否定し続けることは少ない", "できない自分も含めて、自分だと思える", "失敗しても、自分の価値が下がるとは感じにくい", "自分の短所を見ると、強く落ち込んでしまう", "弱みを指摘されると、必要以上に引きずってしまう", "できない自分を受け入れるのは難しい" ].map((t, i) => ({ id: i + 25, cat: 'self', factor: 'D', text: t, isRev: i >= 5 })), ...[ "失敗は成長の材料になると思っている", "つまずいた経験から学べたと感じることがある", "過去の経験が、今の判断に活きていると感じる", "うまくいかなかった出来事にも意味を見出そうとする", "経験を重ねることで、自分は成長できると思う", "失敗した経験は、できれば思い出したくない", "過去の失敗を振り返っても、あまり意味はないと思う", "嫌な経験は忘れた方が前向きだと思う" ].map((t, i) => ({ id: i + 33, cat: 'self', factor: 'E', text: t, isRev: i >= 5 })), ...Array.from({length: 120}, (_, idx) => { const id = idx + 41; const cat = id <= 80 ? 'others' : id <= 120 ? 'achievement' : 'adaptive'; const factorIdx = Math.floor(((id - 1) % 40) / 8); const factorKey = String.fromCharCode(65 + factorIdx); const factorNames = { others: ['傾聴姿勢', '視点移動', '判断保留', '役割理解', '関係配慮'], achievement: ['内発動機', '成長志向', '粘り強さ', '強み活用', '挫折耐性'], adaptive: ['対立耐性', '対話姿勢', '両立思考', '第三案創出', '合意形成'] }; const texts = [ `【${factorNames[cat][factorIdx]}】に関する設問 ${((id - 1) % 8) + 1}番目の内容です。あなたの日常的な意識や行動に近いものを選んでください。`, "相手の話を最後まで聞こうと意識している", "相手が話している途中で口を挟まないようにしている", "話を聞くとき、相手の言いたいことを理解しようと努める", "相手の話を要約して確認することがある", "自分の意見より、まず相手の話を聞くことを大切にしている", "相手の話を聞きながら、つい反論を考えてしまう", "相手の話が長いと、集中力が切れてしまう", "相手の話を十分に聞かずに結論を出してしまうことがある" ]; return { id, cat, factor: factorKey, text: texts[1 + ((id - 1) % 8)], isRev: ((id - 1) % 8) >= 5 }; }) ]; export default function App() { const [view, setView] = useState('landing'); const [user, setUser] = useState(null); const [profile, setProfile] = useState({ name: '', age: '', gender: '', profession: '' }); const [answers, setAnswers] = useState({}); const [currentIdx, setCurrentIdx] = useState(0); const [aiReport, setAiReport] = useState(""); const [isGenerating, setIsGenerating] = useState(false); const [syncStatus, setSyncStatus] = useState('idle'); useEffect(() => { const unsub = onAuthStateChanged(auth, setUser); if (!user) signInAnonymously(auth); return () => unsub(); }, [user]); const results = useMemo(() => { if (view !== 'result') return null; const scores = { self: { total: 0, A: 0, B: 0, C: 0, D: 0, E: 0 }, others: { total: 0, A: 0, B: 0, C: 0, D: 0, E: 0 }, achievement: { total: 0, A: 0, B: 0, C: 0, D: 0, E: 0 }, adaptive: { total: 0, A: 0, B: 0, C: 0, D: 0, E: 0 } }; QUESTIONS.forEach(q => { let val = answers[q.id] || 3; if (q.isRev) val = 6 - val; scores[q.cat].total += val; if (q.factor) scores[q.cat][q.factor] += val; }); return scores; }, [view, answers]); const handleAnswer = (val) => { setAnswers({ ...answers, [QUESTIONS[currentIdx].id]: val }); if (currentIdx < QUESTIONS.length - 1) { setCurrentIdx(currentIdx + 1); } else { setView('result'); window.scrollTo(0, 0); } }; const generateReport = async () => { setIsGenerating(true); const apiKey = ""; const summary = `自分:${results.self.total}, 他者:${results.others.total}, 意欲:${results.achievement.total}, 適応:${results.adaptive.total}`; const prompt = `受講者名: ${profile.name} (${profile.profession})。診断スコア: ${summary}。JOBEEのAIコーチとして、受講者が自信を持てるようなキャリア戦略を600文字で執筆してください。`; try { const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] }) }); const data = await res.json(); const text = data.candidates[0].content.parts[0].text; setAiReport(text); // AIレポート生成「完了後」にスプレッドシートへ全データを送信 syncToSpreadsheet(text); } catch (e) { alert("AI解析に失敗しました。"); } finally { setIsGenerating(false); } }; const syncToSpreadsheet = async (reportText) => { if (!GAS_WEBAPP_URL) return; setSyncStatus('loading'); const data = { timestamp: new Date().toLocaleString('ja-JP'), name: profile.name, age: profile.age, gender: profile.gender, profession: profile.profession, score_self: results.self.total, score_others: results.others.total, score_achievement: results.achievement.total, score_adaptive: results.adaptive.total, ai_report: reportText // ここにAIレポートを込めています }; try { await fetch(GAS_WEBAPP_URL, { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); setSyncStatus('success'); } catch (e) { setSyncStatus('error'); } }; const handlePrint = () => { window.print(); }; const getLevel = (score) => { if (score >= 32) return 'high'; if (score >= 21) return 'mid'; return 'low'; }; // --- RENDERING --- if (view === 'landing') { return (
160問 精密非認知能力診断
{profile.name} 様
{profile.profession} | {new Date().toLocaleDateString()}
あなたの非認知能力の現在地を精密に可視化しました。
Personalized Career Insight
{aiReport}
Analysis: {levelLabel}
{info[level]}
{level === 'high' ? info.adv : info.train}
JOBEE Assessment Protocol v14.0 | Developed for Onefamily