import React, { useState, useMemo, useEffect } from 'react';
import { Leaf, Droplets, Scissors, Move, Eye, RotateCcw, Share2, Flower2, Sprout, Info, Sparkles, Loader2 } from 'lucide-react';
const App = () => {
const [step, setStep] = useState('cover');
const [answers, setAnswers] = useState([]);
const [aiAnalysis, setAiAnalysis] = useState(null);
const [isLoadingAi, setIsLoadingAi] = useState(false);
const [error, setError] = useState(null);
const apiKey = "AIzaSyA2noP8OT__6vNLdUZlAqj61z031-_Gcqo"; // API Key 由執行環境自動注入
const types = {
A: { name: '灌溉型', action: '給予與投入', icon: , color: '#4A90E2', desc: '傾向加法,深信充足的養分與投入是成長的關鍵。' },
B: { name: '修剪型', action: '整理與減法', icon: , color: '#7DAA92', desc: '傾向減法,透過捨棄與整理來留出純粹的生長空間。' },
C: { name: '移植型', action: '調整與重構', icon: , color: '#D4A373', desc: '傾向重構,相信環境的調整能改變生命當前的處境。' },
D: { name: '守望型', action: '觀察與節奏', icon: , color: '#6B705C', desc: '傾向觀察,尊重自然的節奏,在安靜中等待時機。' }
};
const questions = [
{
id: 1,
title: '今天你走進一座花園,第一個會注意到什麼?',
options: [
{ key: 'A', text: '哪裡看起來最乾、最需要水' },
{ key: 'B', text: '哪些地方長得太亂、不夠整齊' },
{ key: 'C', text: '有沒有哪株植物放錯了位置' },
{ key: 'D', text: '整體氛圍,好像少了點生氣' }
]
},
{
id: 2,
title: '今天你想對這座花園進行什麼動作?',
options: [
{ key: 'A', text: '補水、施肥,讓它快點好起來' },
{ key: 'B', text: '修剪、整理,把不需要的拿掉' },
{ key: 'C', text: '移動位置,替植物換個環境' },
{ key: 'D', text: '先不動,花點時間觀察變化' }
]
},
{
id: 3,
title: '經過細心照料,但花園一直沒有開花,你會怎麼做?',
options: [
{ key: 'A', text: '再調整配方,試試不同的養分' },
{ key: 'B', text: '回頭檢查,是不是哪裡做錯了' },
{ key: 'C', text: '思考是否該重新規劃整座花園' },
{ key: 'D', text: '接受現在的狀態,繼續等季節' }
]
},
{
id: 4,
title: '你覺得現在這座花園,最需要什麼?',
options: [
{ key: 'A', text: '空氣與間距,讓它能呼吸' },
{ key: 'B', text: '少一點干預,多一點耐心' },
{ key: 'C', text: '時間,讓根慢慢扎深' },
{ key: 'D', text: '穩定的照看,而不是急著成果' }
]
}
];
const resultData = useMemo(() => {
if (answers.length < 4) return null;
const counts = answers.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
const sortedTypes = Object.entries(counts).sort((a, b) => b[1] - a[1]);
const primary = sortedTypes[0][0];
const secondary = sortedTypes.length > 1 ? sortedTypes[1][0] : null;
return { primary, secondary, counts };
}, [answers]);
// Gemini API 整合邏輯
useEffect(() => {
if (step === 'result' && resultData && !aiAnalysis) {
fetchAiAnalysis();
}
}, [step, resultData]);
const fetchAiAnalysis = async (retryCount = 0) => {
setIsLoadingAi(true);
setError(null);
const prompt = `使用者在「成為自己生命的園丁」心理引導中選擇了以下傾向:主要為${types[resultData.primary].name},次要為${resultData.secondary ? types[resultData.secondary].name : '無'}。請根據《僧人心態》的哲學,以溫和、不說教、富有洞見的語氣,為這座「生命花園」寫一段 100 字以內的深層觀察。不要評價好壞,重點在於覺察與節奏。`;
try {
const response = 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 }] }],
systemInstruction: { parts: [{ text: "你是一位精通《僧人心態》的生命引導者。你的語言風格簡潔、充滿空間感、成熟且溫暖。你從不使用標籤化的語言,而是將生命比喻為一座花園。" }] }
})
});
if (!response.ok) throw new Error('API request failed');
const data = await response.json();
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
setAiAnalysis(text);
} catch (err) {
if (retryCount < 5) {
const delay = Math.pow(2, retryCount) * 1000;
setTimeout(() => fetchAiAnalysis(retryCount + 1), delay);
} else {
setError('暫時無法連線至智慧導引,請參考下方的園丁任務。');
}
} finally {
setIsLoadingAi(false);
}
};
const handleAnswer = (key) => {
const newAnswers = [...answers, key];
setAnswers(newAnswers);
if (newAnswers.length < questions.length) {
setStep(`q${newAnswers.length + 1}`);
} else {
setStep('result');
}
};
const reset = () => {
setAnswers([]);
setStep('cover');
setAiAnalysis(null);
setError(null);
};
const Background = () => (
);
return (
{step === 'cover' && (
成為自己生命的園丁
選擇你此刻的直覺,看看花園正在發生什麼
)}
{questions.map((q, idx) => step === `q${idx + 1}` && (
{q.title}
{q.options.map((opt) => (
))}
))}
{step === 'result' && resultData && (
當前生態觀察
{resultData.secondary
? `${types[resultData.primary].name} × ${types[resultData.secondary].name}`
: `核心 ${types[resultData.primary].name}`}
{/* AI 分析區塊 */}
{isLoadingAi ? (
正在觀察你的花園...
) : error ? (
{error}
) : (
「{aiAnalysis || "真正的園丁,不是選對工具,而是知道什麼時候該換手。"}」
)}
{/* 園丁身分圖鑑 */}
認識園丁角色
{Object.entries(types).map(([key, type]) => (
{type.icon}
{type.name}
{resultData.counts[key] > 0 &&
Presence: {resultData.counts[key]}}
))}
)}
);
};
export default App;