File size: 9,285 Bytes
ad08f08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import React, { useState, useEffect } from 'react';

const DirectoryPage = () => {
  const [organizations, setOrganizations] = useState([]);
  const [loading, setLoading] = useState(true);
  const [searchTerm, setSearchTerm] = useState('');
  const [sectorFilter, setSectorFilter] = useState('All');

  useEffect(() => {
    // In a real app, this would fetch from an API
    // For demo purposes, we'll use mock data
    const mockOrganizations = [
      {
        id: 1,
        name: 'Global Food Rescue Initiative',
        sector: 'NGO',
        country: 'International',
        description: 'Non-profit organization focused on reducing food waste through redistribution networks.',
        expertise: ['Food Recovery', 'Logistics', 'Volunteer Management'],
        projects: 42
      },
      {
        id: 2,
        name: 'AgriTech Solutions Ltd',
        sector: 'Private',
        country: 'Netherlands',
        description: 'Technology company developing smart cold chain solutions for perishable goods.',
        expertise: ['Cold Chain Technology', 'IoT Sensors', 'Data Analytics'],
        projects: 18
      },
      {
        id: 3,
        name: 'Sustainable Agriculture Research Institute',
        sector: 'Academic',
        country: 'United States',
        description: 'Research institution studying post-harvest loss reduction techniques.',
        expertise: ['Research', 'Post-harvest Technology', 'Training'],
        projects: 27
      },
      {
        id: 4,
        name: 'Ministry of Agriculture and Food Security',
        sector: 'Government',
        country: 'Kenya',
        description: 'Government agency implementing national food loss reduction programs.',
        expertise: ['Policy Development', 'Program Implementation', 'Farmer Support'],
        projects: 15
      },
      {
        id: 5,
        name: 'Circular Economy Food Partners',
        sector: 'NGO',
        country: 'Germany',
        description: 'Organization promoting circular economy approaches to food systems.',
        expertise: ['Circular Economy', 'Composting', 'Waste Valorization'],
        projects: 33
      },
      {
        id: 6,
        name: 'Farm to Market Logistics Co.',
        sector: 'Private',
        country: 'Brazil',
        description: 'Logistics company specializing in transportation of perishable agricultural products.',
        expertise: ['Transportation', 'Cold Chain Logistics', 'Supply Chain'],
        projects: 29
      }
    ];

    setTimeout(() => {
      setOrganizations(mockOrganizations);
      setLoading(false);
    }, 500);
  }, []);

  const sectors = ['All', ...new Set(organizations.map(org => org.sector))];

  const filteredOrganizations = organizations.filter(org => {
    const matchesSearch = org.name.toLowerCase().includes(searchTerm.toLowerCase()) || 
                          org.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
                          org.expertise.some(exp => exp.toLowerCase().includes(searchTerm.toLowerCase()));
    
    const matchesSector = sectorFilter === 'All' || org.sector === sectorFilter;
    
    return matchesSearch && matchesSector;
  });

  if (loading) {
    return (
      <div className="py-16 bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 transition-colors duration-300 min-h-screen">
        <div className="container mx-auto px-4">
          <h2 className="text-3xl font-bold mb-8 text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-bio-green to-bio-blue bg-clip-text text-transparent">Stakeholder Directory</h2>
          <div className="flex justify-center">
            <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-bio-green"></div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="py-16 bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 transition-colors duration-300 min-h-screen">
      <div className="container mx-auto px-4">
        <h2 className="text-3xl font-bold mb-8 text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-bio-green to-bio-blue bg-clip-text text-transparent">Stakeholder Directory</h2>
        
        <div className="mb-8 bg-white dark:bg-gray-700 rounded-2xl shadow-lg p-6 border border-gray-100 dark:border-gray-600 bg-gradient-to-br from-white to-gray-100 dark:from-gray-700 dark:to-gray-800">
          <div className="flex flex-col md:flex-row gap-4">
            <div className="flex-grow">
              <input
                type="text"
                placeholder="Search organizations..."
                className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-bio-green focus:border-transparent dark:bg-gray-600 dark:text-white drop-shadow bg-gradient-to-r from-white to-gray-50 dark:from-gray-600 dark:to-gray-700"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
              />
            </div>
            <div className="w-full md:w-48">
              <select
                className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-bio-green focus:border-transparent dark:bg-gray-600 dark:text-white drop-shadow bg-gradient-to-r from-white to-gray-50 dark:from-gray-600 dark:to-gray-700"
                value={sectorFilter}
                onChange={(e) => setSectorFilter(e.target.value)}
              >
                {sectors.map(sector => (
                  <option key={sector} value={sector}>{sector}</option>
                ))}
              </select>
            </div>
          </div>
        </div>
        
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          {filteredOrganizations.map((org) => (
            <div key={org.id} className="bg-white dark:bg-gray-700 rounded-2xl shadow-lg overflow-hidden hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 border border-gray-100 dark:border-gray-600 bg-gradient-to-br from-white to-gray-100 dark:from-gray-700 dark:to-gray-800">
              <div className="p-6">
                <div className="flex justify-between items-start mb-4">
                  <h3 className="text-xl font-bold text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent dark:from-white dark:to-gray-300">{org.name}</h3>
                  <span className="inline-block px-3 py-1 text-xs font-semibold text-bio-purple bg-purple-100 dark:bg-purple-900/30 dark:text-purple-300 rounded-full drop-shadow bg-gradient-to-r from-purple-100 to-purple-200 dark:from-purple-900/30 dark:to-purple-800/30">
                    {org.sector}
                  </span>
                </div>
                
                <div className="mb-4">
                  <span className="text-sm text-gray-500 dark:text-gray-400 drop-shadow">{org.country}</span>
                </div>
                
                <p className="text-gray-600 dark:text-gray-300 mb-4 drop-shadow">{org.description}</p>
                
                <div className="mb-4">
                  <h4 className="font-semibold text-gray-800 dark:text-white mb-2 drop-shadow bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent dark:from-white dark:to-gray-300">Expertise:</h4>
                  <div className="flex flex-wrap gap-2">
                    {org.expertise.map((exp, index) => (
                      <span key={index} className="px-2 py-1 text-xs bg-gray-200 dark:bg-gray-600 text-gray-700 dark:text-gray-300 rounded-full drop-shadow bg-gradient-to-r from-gray-200 to-gray-300 dark:from-gray-600 dark:to-gray-700">
                        {exp}
                      </span>
                    ))}
                  </div>
                </div>
                
                <div className="flex justify-between items-center">
                  <span className="text-sm text-gray-500 dark:text-gray-400 drop-shadow">{org.projects} projects</span>
                  <button className="bg-gradient-to-r from-bio-purple to-purple-500 text-white px-4 py-2 rounded-lg hover:from-purple-500 hover:to-purple-600 transition shadow-md hover:shadow-lg drop-shadow">
                    Contact
                  </button>
                </div>
              </div>
            </div>
          ))}
        </div>
        
        {filteredOrganizations.length === 0 && (
          <div className="text-center py-12 bg-white dark:bg-gray-700 rounded-2xl shadow-lg bg-gradient-to-br from-white to-gray-100 dark:from-gray-700 dark:to-gray-800">
            <p className="text-gray-600 dark:text-gray-400 drop-shadow">No organizations found matching your criteria.</p>
            <button 
              className="mt-4 text-bio-purple dark:text-purple-400 hover:underline drop-shadow bg-gradient-to-r from-bio-purple to-purple-500 bg-clip-text text-transparent"
              onClick={() => {
                setSearchTerm('');
                setSectorFilter('All');
              }}
            >
              Clear filters
            </button>
          </div>
        )}
      </div>
    </div>
  );
};

export default DirectoryPage;