1 import { useQuery } from "@tanstack/react-query";
2 import type { RepairGuide } from "@shared/schema";
3 import { Cpu, Code, Eraser, MoveUp, XCircle } from "lucide-react";
4 import { cn } from "@/lib/utils";
5
6 interface CategoryGridProps {
7 selectedCategory: string;
8 onCategoryChange: (category: string) => void;
9 deviceType: string;
10 }
11
12 export default function CategoryGrid({ selectedCategory, onCategoryChange, deviceType }: CategoryGridProps) {
13 const { data: allGuides = [] } = useQuery<RepairGuide[]>({
14 queryKey: ["api", "repair-guides"],
15 });
16
17 const categories = [
18 {
19 id: "hardware",
20 name: "Hardware",
21 description: "Components & builds",
22 icon: Cpu,
23 color: "text-indigo-500",
24 bgColor: "bg-indigo-500/10",
25 },
26 {
27 id: "software",
28 name: "Software",
29 description: "OS & Driver fixes",
30 icon: Code,
31 color: "text-emerald-500",
32 bgColor: "bg-emerald-500/10",
33 },
34 {
35 id: "cleaning",
36 name: "Cleaning",
37 description: "Pro maintenance",
38 icon: Eraser,
39 color: "text-amber-500",
40 bgColor: "bg-amber-500/10",
41 },
42 {
43 id: "upgrades",
44 name: "Upgrades",
45 description: "Performance boosts",
46 icon: MoveUp,
47 color: "text-purple-500",
48 bgColor: "bg-purple-500/10",
49 },
50 ];
51
52 const getCategoryCount = (categoryId: string) => {
53 return allGuides.filter(guide =>
54 guide.category === categoryId &&
55 (!deviceType || guide.deviceType === deviceType)
56 ).length;
57 };
58
59 return (
60 <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
61 {categories.map((category) => {
62 const isActive = selectedCategory === category.id;
63 const Icon = category.icon;
64
65 return (
66 <button
67 key={category.id}
68 onClick={() => onCategoryChange(isActive ? "" : category.id)}
69 className={cn(
70 "group relative p-6 rounded-[2rem] border transition-all duration-500 text-left overflow-hidden",
71 isActive
72 ? "bg-primary border-primary shadow-glass text-primary-foreground"
73 : "bg-card/40 backdrop-blur-sm border-border/40 hover:border-primary/40 hover:shadow-elegant"
74 )}
75 >
76 <div className={cn(
77 "h-12 w-12 rounded-2xl flex items-center justify-center mb-6 transition-all duration-500",
78 isActive ? "bg-white/20" : category.bgColor,
79 !isActive && "group-hover:scale-110"
80 )}>
81 <Icon className={cn("h-6 w-6", isActive ? "text-white" : category.color)} />
82 </div>
83
84 <h3 className="font-bold text-lg mb-1">{category.name}</h3>
85 <p className={cn(
86 "text-xs mb-4 line-clamp-1",
87 isActive ? "text-white/80" : "text-muted-foreground"
88 )}>
89 {category.description}
90 </p>
91
92 <div className="flex items-center justify-between">
93 <span className={cn(
94 "text-[10px] font-black uppercase tracking-widest px-2.5 py-1 rounded-full",
95 isActive ? "bg-white/20 text-white" : "bg-muted text-muted-foreground"
96 )}>
97 {getCategoryCount(category.id)} guides
98 </span>
99
100 {isActive && <XCircle className="h-4 w-4 text-white/60 animate-in fade-in zoom-in" />}
101 </div>
102
103 {/* Decorative background glow for inactive items */}
104 {!isActive && (
105 <div className={cn(
106 "absolute -right-4 -bottom-4 h-16 w-16 opacity-0 group-hover:opacity-20 blur-2xl rounded-full transition-opacity duration-500",
107 category.bgColor.replace("/10", "")
108 )} />
109 )}
110 </button>
111 );
112 })}
113 </div>
114 );
115 }