File size: 6,473 Bytes
8139e18
 
c63c36c
 
8139e18
c63c36c
8139e18
c63c36c
8139e18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c63c36c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8139e18
 
 
 
 
 
 
 
 
 
 
 
c63c36c
 
 
 
 
 
 
 
 
 
 
 
 
 
f1588df
 
 
 
 
 
 
 
c63c36c
 
 
8139e18
c63c36c
 
 
 
 
 
 
 
8139e18
c63c36c
 
 
 
 
 
 
 
 
 
 
8139e18
c63c36c
 
 
 
 
f1588df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8139e18
 
c63c36c
 
 
 
8139e18
 
 
 
 
 
 
 
 
 
 
 
 
 
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
'use client'

import { useState, useEffect } from 'react'
import { ArrowRight, Loader2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { api } from '@/lib/api'

const staticProjects = [
  {
    title: 'AgriTech Nepal',
    description: 'Smart agricultural solutions connecting farmers with modern technology to improve crop yield and reduce costs',
    image: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
    tags: ['Agriculture', 'IoT', 'Data Analytics'],
    contributors: 12,
  },
  {
    title: 'WDUBot',
    description: 'An intelligent bot platform for Nepali universities providing academic support and administrative assistance',
    image: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
    tags: ['AI', 'Education', 'Chatbot'],
    contributors: 8,
  },
  {
    title: 'HealthLink',
    description: 'Connecting patients with healthcare providers in remote areas of Nepal through telemedicine platform',
    image: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
    tags: ['Healthcare', 'Telemedicine', 'Web'],
    contributors: 15,
  },
]

export function FeaturedProjects() {
  const [projects, setProjects] = useState<any[]>([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const loadProjects = async () => {
      try {
        const data = await api.projects.list()
        if (data && data.length > 0) {
          setProjects(data)
        } else {
          setProjects(staticProjects)
        }
      } catch (error) {
        console.error('Failed to fetch projects:', error)
        setProjects(staticProjects)
      } finally {
        setLoading(false)
      }
    }
    loadProjects()
  }, [])

  return (
    <section id="featured-projects" className="py-12 sm:py-16 md:py-20 px-4 md:px-6 bg-muted/30 scroll-mt-20" aria-labelledby="projects-heading">
      <div className="container mx-auto">
        <div className="text-center mb-10 sm:mb-12 md:mb-16">
          <h2 id="projects-heading" className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-foreground mb-3 sm:mb-4">
            Featured Projects
          </h2>
          <p className="text-sm sm:text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-2">
            Showcasing innovative solutions built by our community members
          </p>
        </div>

        {loading ? (
          <div className="flex justify-center py-20">
            <Loader2 className="w-8 h-8 animate-spin text-primary" />
          </div>
        ) : (
          <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6 md:gap-8 max-w-6xl mx-auto">
            {projects.map((project, index) => (
              <article
                key={index}
                className="bg-card rounded-xl sm:rounded-2xl overflow-hidden border border-border hover:border-primary transition-all duration-300 hover:shadow-xl group"
              >
                {/* Project Image */}
                <div
                  className="h-36 sm:h-40 md:h-48 bg-cover bg-center group-hover:scale-110 transition-transform duration-300"
                  style={{
                    background: project.image?.startsWith('linear-gradient') || !project.image
                      ? (project.image || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)')
                      : undefined,
                    backgroundImage: project.image && !project.image.startsWith('linear-gradient')
                      ? `url(${project.image})`
                      : undefined
                  }}
                  role="img"
                  aria-label={`${project.title} project visual`}
                />

                {/* Project Content */}
                <div className="p-4 sm:p-5 md:p-6">
                  <h3 className="text-lg sm:text-xl md:text-2xl font-bold text-foreground mb-1.5 sm:mb-2">
                    {project.title}
                  </h3>
                  <p className="text-sm sm:text-base text-muted-foreground mb-3 sm:mb-4 leading-relaxed line-clamp-3">
                    {project.description}
                  </p>

                  {/* Tags */}
                  <div className="flex flex-wrap gap-1.5 sm:gap-2 mb-3 sm:mb-4">
                    {(project.tags || []).map((tag: string) => (
                      <span
                        key={tag}
                        className="text-[10px] sm:text-xs font-medium bg-primary/10 text-primary px-2 sm:px-3 py-0.5 sm:py-1 rounded-full"
                      >
                        {tag}
                      </span>
                    ))}
                  </div>

                  {/* Contributors and View Button */}
                  <div className="flex items-center justify-between">
                    <div className="text-xs sm:text-sm text-muted-foreground">
                      <span className="font-semibold text-foreground">{project.contributors || 0}</span> contributors
                    </div>
                    {project.link ? (
                      <Button
                        variant="ghost"
                        size="sm"
                        className="text-primary hover:text-primary/80 text-xs sm:text-sm px-2 sm:px-3"
                        asChild
                      >
                        <a href={project.link} target="_blank" rel="noopener noreferrer">
                          View <ArrowRight className="w-3 h-3 sm:w-4 sm:h-4 ml-1 sm:ml-2" aria-hidden="true" />
                        </a>
                      </Button>
                    ) : (
                      <Button
                        variant="ghost"
                        size="sm"
                        className="text-primary hover:text-primary/80 text-xs sm:text-sm px-2 sm:px-3"
                        disabled
                      >
                        View <ArrowRight className="w-3 h-3 sm:w-4 sm:h-4 ml-1 sm:ml-2" aria-hidden="true" />
                      </Button>
                    )}
                  </div>
                </div>
              </article>
            ))}
          </div>
        )}

        {/* See All Projects Button */}
        <div className="text-center mt-8 sm:mt-10 md:mt-12">
          <Button
            size="lg"
            className="bg-gradient-to-r from-primary to-secondary hover:opacity-90 text-sm sm:text-base px-6 sm:px-8"
          >
            See All Projects
          </Button>
        </div>
      </div>
    </section>
  )
}