File size: 4,929 Bytes
81d1e4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7a6a641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81d1e4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useQuery } from "@tanstack/react-query";
import { projectsService } from "@/services/projects.service";
import { ProjectCard } from "@/components/cards/ProjectCard";
import { ProjectModal } from "@/components/modals/ProjectModal";
import { FadeIn } from "@/components/animations/FadeIn";
import { Skeleton } from "@/components/common/Skeleton";
import type { Project } from "@/types";
import { Search } from "lucide-react";

export function ProjectsSection() {
  const { t } = useTranslation();
  const [search, setSearch] = useState("");
  const [category, setCategory] = useState("");
  const [selectedProject, setSelectedProject] = useState<Project | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ["projects", search, category],
    queryFn: () => projectsService.getAll({ search, category }),
  });

  const projects: Project[] = data?.data?.data || [];
  const categories = [...new Set(projects.map((p) => p.categoryEn))];

  return (
    <section id="projects" className="py-20">
      <div className="max-w-7xl mx-auto px-4">
        <FadeIn>
          <h2 className="text-3xl font-bold text-center text-slate-900 dark:text-white mb-8">{t("projects.title")}</h2>
        </FadeIn>

        <FadeIn>
          <div className="flex flex-col sm:flex-row gap-4 justify-center mb-8">
            <div className="relative max-w-md w-full mx-auto sm:mx-0">
              <Search className="absolute left-3 top-3 w-4 h-4 text-slate-400" />
              <input
                type="text"
                placeholder={t("projects.search")}
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                className="w-full pl-10 pr-4 py-2 rounded-lg border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
              />
            </div>
            <div className="flex gap-2 justify-center flex-wrap">
              <button
                onClick={() => setCategory("")}
                className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                  !category ? "bg-blue-600 text-white" : "bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-700"
                }`}
              >
                {t("projects.all")}
              </button>
              {categories.map((cat) => (
                <button
                  key={cat}
                  onClick={() => setCategory(cat)}
                  className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                    category === cat ? "bg-blue-600 text-white" : "bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-700"
                  }`}
                >
                  {cat}
                </button>
              ))}
            </div>
          </div>
        </FadeIn>

        {isLoading ? (
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {Array.from({ length: 6 }).map((_, i) => (
              <div key={i} className="bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-slate-800 overflow-hidden">
                <div className="relative h-56 bg-slate-200 dark:bg-slate-800 animate-pulse">
                  <div className="absolute top-4 right-4 w-12 h-12 rounded-full bg-slate-300 dark:bg-slate-700" />
                </div>
                <div className="p-5 space-y-3">
                  <div className="h-5 w-20 bg-slate-200 dark:bg-slate-800 rounded-full" />
                  <div className="h-5 w-3/4 bg-slate-200 dark:bg-slate-800 rounded" />
                  <div className="space-y-2">
                    <div className="h-3 w-full bg-slate-200 dark:bg-slate-800 rounded" />
                    <div className="h-3 w-2/3 bg-slate-200 dark:bg-slate-800 rounded" />
                  </div>
                  <div className="flex gap-2 pt-1">
                    <div className="h-6 w-16 bg-slate-200 dark:bg-slate-800 rounded" />
                    <div className="h-6 w-16 bg-slate-200 dark:bg-slate-800 rounded" />
                  </div>
                </div>
              </div>
            ))}
          </div>
        ) : (
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {projects.map((project, i) => (
              <FadeIn key={project.id} delay={i * 0.1}>
                <ProjectCard project={project} onClick={() => setSelectedProject(project)} />
              </FadeIn>
            ))}
          </div>
        )}

        <ProjectModal project={selectedProject} open={!!selectedProject} onClose={() => setSelectedProject(null)} />
      </div>
    </section>
  );
}