File size: 6,041 Bytes
be02369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import React, { useState, useCallback } from 'react';
import { BugIcon, SparklesIcon, AlertTriangleIcon } from '../components/icons';
import Spinner from '../components/Spinner';
import { generatePestLibrary, isAIConfigured } from '../services/geminiService';
import type { PestLibraryEntry, View } from '../types';
import { AppStatus } from '../types';

interface PestLibraryViewProps {
  setActiveView: (view: View) => void;
}

const PestLibraryView: React.FC<PestLibraryViewProps> = ({ setActiveView }) => {
  const [status, setStatus] = useState<AppStatus>(AppStatus.IDLE);
  const [location, setLocation] = useState<string>('');
  const [pestData, setPestData] = useState<PestLibraryEntry[] | null>(null);
  const [error, setError] = useState<string>('');
  const aiConfigured = isAIConfigured();

  const handleGenerate = useCallback(async () => {
    if (!location.trim()) {
      setError('Please enter your city or region.');
      return;
    }
    setStatus(AppStatus.ANALYZING);
    setError('');
    setPestData(null);

    try {
      const result = await generatePestLibrary(location);
      if (result) {
        setPestData(result);
        setStatus(AppStatus.SUCCESS);
      } else {
        throw new Error('Failed to generate the pest library. The AI may be busy. Please try again.');
      }
    } catch (e: any) {
      setError(e.message);
      setStatus(AppStatus.ERROR);
    }
  }, [location]);

  return (
    <div className="space-y-8 max-w-4xl mx-auto">
      <header className="text-center">
        <h2 className="text-3xl font-bold tracking-tight text-stone-900 sm:text-4xl flex items-center justify-center gap-3">
          <BugIcon className="w-8 h-8 text-red-600" />
          Regional Pest Library
        </h2>
        <p className="mt-4 text-lg leading-8 text-stone-600">
          Discover common pests and diseases for bonsai in your area to stay one step ahead.
        </p>
      </header>

      <div className="bg-white p-6 rounded-xl shadow-lg border border-stone-200">
        <div className="flex flex-col sm:flex-row gap-4">
          <input
            type="text"
            value={location}
            onChange={(e) => setLocation(e.target.value)}
            className="block w-full rounded-md border-0 py-2 px-3 text-stone-900 shadow-sm ring-1 ring-inset ring-stone-300 placeholder:text-stone-400 focus:ring-2 focus:ring-inset focus:ring-green-600 sm:text-sm sm:leading-6"
            placeholder="e.g., Portland, Oregon"
            disabled={status === AppStatus.ANALYZING}
          />
          <button
            onClick={handleGenerate}
            disabled={status === AppStatus.ANALYZING || !aiConfigured}
            className="flex items-center justify-center gap-2 w-full sm:w-auto rounded-md bg-green-700 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-green-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-700 disabled:bg-stone-400 disabled:cursor-not-allowed"
          >
            <SparklesIcon className="w-5 h-5" />
            {status === AppStatus.ANALYZING ? 'Generating...' : 'Generate Library'}
          </button>
        </div>
        {error && <p className="text-sm text-red-600 mt-2">{error}</p>}
        {!aiConfigured && (
            <div className="mt-4 p-3 bg-yellow-50 text-yellow-800 rounded-lg border border-yellow-200 text-center">
                <p className="text-sm">
                  AI features are disabled. Please set your Gemini API key in the{' '}
                  <button onClick={() => setActiveView('settings')} className="font-bold underline hover:text-yellow-900">
                    Settings page
                  </button>.
                </p>
            </div>
        )}
      </div>

      {status === AppStatus.ANALYZING && <Spinner text="Yuki is consulting the archives..." />}
      {status === AppStatus.SUCCESS && pestData && (
        <div className="bg-white p-6 rounded-xl shadow-lg border border-stone-200 space-y-4">
          <h3 className="text-xl font-bold text-stone-800">Pest & Disease Guide for {location}</h3>
           {pestData.map((pest, i) => (
              <details key={i} className="p-4 bg-stone-50 rounded-lg border border-stone-200 group">
                  <summary className="font-semibold text-stone-800 cursor-pointer flex justify-between items-center">
                      {pest.name} ({pest.type})
                      <span className="text-xs text-stone-500 group-open:hidden">Show Details</span>
                      <span className="text-xs text-stone-500 hidden group-open:inline">Hide Details</span>
                  </summary>
                  <div className="mt-4 space-y-3 text-sm text-stone-700">
                      <p>{pest.description}</p>
                      <div>
                          <strong className="font-medium text-stone-800">Symptoms:</strong>
                          <ul className="list-disc list-inside ml-2">
                              {pest.symptoms.map((s, idx) => <li key={idx}>{s}</li>)}
                          </ul>
                      </div>
                      <div>
                          <strong className="font-medium text-stone-800">Organic Treatment:</strong>
                          <p>{pest.treatment.organic}</p>
                      </div>
                        <div>
                          <strong className="font-medium text-stone-800">Chemical Treatment:</strong>
                          <p>{pest.treatment.chemical}</p>
                      </div>
                  </div>
              </details>
          ))}
        </div>
      )}
       {status === AppStatus.ERROR && (
            <div className="text-center p-8 bg-white rounded-lg shadow-lg border border-red-200 max-w-md mx-auto">
                <h3 className="text-xl font-semibold text-red-700">An Error Occurred</h3>
                <p className="text-stone-600 mt-2">{error}</p>
            </div>
       )}
    </div>
  );
};

export default PestLibraryView;