1 import { useState } from "react";
2 import { useQuery } from "@tanstack/react-query";
3 import type { DeviceComponent } from "@shared/schema";
4
5 interface PartsIdentificationProps {
6 deviceType: string;
7 }
8
9 export default function PartsIdentification({ deviceType }: PartsIdentificationProps) {
10 const [selectedComponent, setSelectedComponent] = useState<string | null>(null);
11
12 const { data: components = [] } = useQuery<DeviceComponent[]>({
13 queryKey: ["/api/device-components", deviceType],
14 queryFn: () => {
15 const params = new URLSearchParams();
16 if (deviceType) params.append('deviceType', deviceType);
17 return fetch(`/api/device-components?${params}`).then(res => res.json());
18 },
19 });
20
21 const componentColors = [
22 { name: "RAM/Memory", color: "bg-success-600" },
23 { name: "Storage Drive", color: "bg-warning-700" },
24 { name: "Cooling System", color: "bg-cyan-600" },
25 { name: "Battery", color: "bg-purple-600" },
26 { name: "Motherboard", color: "bg-primary-700" },
27 ];
28
29 const getComponentColor = (name: string) => {
30 const component = componentColors.find(c => name.includes(c.name.split('/')[0]));
31 return component?.color || "bg-gray-600";
32 };
33
34 return (
35 <div className="bg-white dark:bg-gray-800 rounded-xl shadow-material p-6">
36 <h2 className="text-lg font-medium text-gray-900 dark:text-white mb-4">Parts Identification Guide</h2>
37 <p className="text-sm text-gray-600 dark:text-gray-300 mb-6">Click on components to learn more about them</p>
38
39 <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
40 <div className="relative">
41 <img
42 src="https://pixabay.com/get/g47f3243ed959354ccf54e02cc790eae822f47a5a3e5222dbc4d9becb7bacd50952bf4d9c647072182a34403929751facc95c030ab418c2af1194144c6770113f_1280.jpg"
43 alt="Laptop internal components layout"
44 className="w-full rounded-lg"
45 />
46
47 {/* Interactive hotspots */}
48 <button
49 onClick={() => setSelectedComponent("ram")}
50 className="absolute top-1/4 left-1/3 w-6 h-6 bg-primary-700 rounded-full border-4 border-white shadow-lg hover:scale-110 transition-transform"
51 title="RAM/Memory"
52 >
53 <span className="sr-only">RAM Module</span>
54 </button>
55 <button
56 onClick={() => setSelectedComponent("storage")}
57 className="absolute top-1/2 left-1/4 w-6 h-6 bg-primary-700 rounded-full border-4 border-white shadow-lg hover:scale-110 transition-transform"
58 title="Storage Drive"
59 >
60 <span className="sr-only">Storage Drive</span>
61 </button>
62 <button
63 onClick={() => setSelectedComponent("cooling")}
64 className="absolute top-1/3 right-1/4 w-6 h-6 bg-primary-700 rounded-full border-4 border-white shadow-lg hover:scale-110 transition-transform"
65 title="Cooling System"
66 >
67 <span className="sr-only">Cooling Fan</span>
68 </button>
69 </div>
70
71 <div className="space-y-4">
72 <div className="border border-gray-200 dark:border-gray-600 rounded-lg p-4">
73 <h3 className="font-medium text-gray-900 dark:text-white mb-2">Common Components</h3>
74 <div className="space-y-2">
75 {components.map((component) => (
76 <button
77 key={component.id}
78 onClick={() => setSelectedComponent(component.id)}
79 className={`flex items-center space-x-3 p-2 w-full rounded cursor-pointer transition-colors ${
80 selectedComponent === component.id ? "bg-primary-50" : "hover:bg-gray-50"
81 }`}
82 >
83 <div className={`w-3 h-3 rounded-full ${getComponentColor(component.name)}`}></div>
84 <span className="text-sm">{component.name}</span>
85 </button>
86 ))}
87 </div>
88 </div>
89
90 {selectedComponent && (
91 <div className="border border-gray-200 rounded-lg p-4">
92 <h4 className="font-medium text-gray-900 mb-2">Component Details</h4>
93 {(() => {
94 const component = components.find(c => c.id === selectedComponent);
95 if (component) {
96 return (
97 <>
98 <p className="text-sm text-gray-600 mb-3">{component.description}</p>
99 {component.safetyNotes.length > 0 && (
100 <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-3">
101 <h5 className="font-medium text-yellow-800 mb-1">Safety Notes</h5>
102 <ul className="text-sm text-yellow-700 space-y-1">
103 {component.safetyNotes.map((note, index) => (
104 <li key={index}>• {note}</li>
105 ))}
106 </ul>
107 </div>
108 )}
109 </>
110 );
111 }
112 return <p className="text-sm text-gray-500">Select a component to view details.</p>;
113 })()}
114 </div>
115 )}
116
117 <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
118 <div className="flex items-start space-x-3">
119 <i className="material-icons text-primary-700 text-lg mt-0.5">info</i>
120 <div>
121 <h4 className="font-medium text-primary-900 mb-1">Pro Tip</h4>
122 <p className="text-sm text-primary-800">
123 Always power down and disconnect the battery before working on internal components.
124 </p>
125 </div>
126 </div>
127 </div>
128 </div>
129 </div>
130 </div>
131 );
132 }