1 import {
2 repairGuides,
3 troubleshootingFlows,
4 deviceComponents,
5 users,
6 favorites,
7 deviceBrands,
8 deviceModels,
9 guideCompatibility,
10 type RepairGuide,
11 type InsertRepairGuide,
12 type TroubleshootingFlow,
13 type InsertTroubleshootingFlow,
14 type DeviceComponent,
15 type InsertDeviceComponent,
16 type User,
17 type InsertUser,
18 type Favorite,
19 type InsertFavorite,
20 type DeviceBrand,
21 type InsertDeviceBrand,
22 type DeviceModel,
23 type InsertDeviceModel,
24 type GuideCompatibility,
25 type InsertGuideCompatibility,
26 } from "@shared/schema";
27 import { db } from "./db";
28 import { eq, and, like, or, sql } from "drizzle-orm";
29
30 export interface IStorage {
31 // User operations
32 getUser(id: string): Promise<User | undefined>;
33 getUserByEmail(email: string): Promise<User | undefined>;
34 createUser(user: InsertUser): Promise<User>;
35 updateUser(id: string, user: Partial<User>): Promise<User | undefined>;
36
37 // Favorites operations
38 getUserFavorites(userId: string): Promise<Favorite[]>;
39 addToFavorites(userId: string, favorite: InsertFavorite): Promise<Favorite>;
40 removeFromFavorites(userId: string, itemId: string, itemType: string): Promise<void>;
41 isFavorited(userId: string, itemId: string, itemType: string): Promise<boolean>;
42
43 // Repair Guides
44 getRepairGuides(filters?: { deviceType?: string; category?: string; difficulty?: string }): Promise<RepairGuide[]>;
45 getRepairGuide(id: string): Promise<RepairGuide | undefined>;
46 createRepairGuide(guide: InsertRepairGuide): Promise<RepairGuide>;
47 updateViewCount(id: string): Promise<void>;
48 updateDownloadCount(id: string): Promise<void>;
49 toggleBookmark(id: string): Promise<RepairGuide | undefined>;
50 searchRepairGuides(query: string): Promise<RepairGuide[]>;
51
52 // Troubleshooting Flows
53 getTroubleshootingFlows(): Promise<TroubleshootingFlow[]>;
54 getTroubleshootingFlow(id: string): Promise<TroubleshootingFlow | undefined>;
55 createTroubleshootingFlow(flow: InsertTroubleshootingFlow): Promise<TroubleshootingFlow>;
56
57 // Device Components
58 getDeviceComponents(deviceType?: string): Promise<DeviceComponent[]>;
59 getDeviceComponent(id: string): Promise<DeviceComponent | undefined>;
60 createDeviceComponent(component: InsertDeviceComponent): Promise<DeviceComponent>;
61
62 // Device Brands and Models
63 getDeviceBrands(deviceType?: string): Promise<DeviceBrand[]>;
64 getDeviceModels(brandId?: string, deviceType?: string): Promise<DeviceModel[]>;
65 getDeviceModel(id: string): Promise<DeviceModel | undefined>;
66 getModelsByBrand(brandId: string): Promise<DeviceModel[]>;
67 searchDeviceModels(query: string, deviceType?: string): Promise<DeviceModel[]>;
68
69 // Guide Compatibility
70 getCompatibleGuides(modelId: string): Promise<RepairGuide[]>;
71 getModelCompatibility(guideId: string): Promise<DeviceModel[]>;
72
73 // User guide creation
74 createUserGuide(guide: InsertRepairGuide): Promise<RepairGuide>;
75 }
76
77 export class DatabaseStorage implements IStorage {
78 // User operations
79 async getUser(id: string): Promise<User | undefined> {
80 const [user] = await db.select().from(users).where(eq(users.id, id));
81 return user;
82 }
83
84 async getUserByEmail(email: string): Promise<User | undefined> {
85 const [user] = await db.select().from(users).where(eq(users.email, email));
86 return user;
87 }
88
89 async createUser(userData: InsertUser): Promise<User> {
90 const [user] = await db.insert(users).values(userData).returning();
91 return user;
92 }
93
94 async updateUser(id: string, userData: Partial<User>): Promise<User | undefined> {
95 const [user] = await db
96 .update(users)
97 .set({ ...userData, updatedAt: new Date() })
98 .where(eq(users.id, id))
99 .returning();
100 return user;
101 }
102
103 // Favorites operations
104 async getUserFavorites(userId: string): Promise<Favorite[]> {
105 return await db.select().from(favorites).where(eq(favorites.userId, userId));
106 }
107
108 async addToFavorites(userId: string, favorite: InsertFavorite): Promise<Favorite> {
109 const [newFavorite] = await db
110 .insert(favorites)
111 .values({ ...favorite, userId })
112 .returning();
113 return newFavorite;
114 }
115
116 async removeFromFavorites(userId: string, itemId: string, itemType: string): Promise<void> {
117 await db
118 .delete(favorites)
119 .where(
120 and(
121 eq(favorites.userId, userId),
122 eq(favorites.itemId, itemId),
123 eq(favorites.itemType, itemType)
124 )
125 );
126 }
127
128 async isFavorited(userId: string, itemId: string, itemType: string): Promise<boolean> {
129 const [favorite] = await db
130 .select()
131 .from(favorites)
132 .where(
133 and(
134 eq(favorites.userId, userId),
135 eq(favorites.itemId, itemId),
136 eq(favorites.itemType, itemType)
137 )
138 );
139 return !!favorite;
140 }
141
142 // Repair Guides operations
143 async getRepairGuides(filters?: { deviceType?: string; category?: string; difficulty?: string }): Promise<RepairGuide[]> {
144 let query = db.select().from(repairGuides);
145
146 if (filters?.deviceType) {
147 query = query.where(eq(repairGuides.deviceType, filters.deviceType));
148 }
149 if (filters?.category) {
150 query = query.where(eq(repairGuides.category, filters.category));
151 }
152 if (filters?.difficulty) {
153 query = query.where(eq(repairGuides.difficulty, filters.difficulty));
154 }
155
156 return await query;
157 }
158
159 async getRepairGuide(id: string): Promise<RepairGuide | undefined> {
160 const [guide] = await db.select().from(repairGuides).where(eq(repairGuides.id, id));
161 return guide;
162 }
163
164 async createRepairGuide(guide: InsertRepairGuide): Promise<RepairGuide> {
165 const [newGuide] = await db.insert(repairGuides).values(guide).returning();
166 return newGuide;
167 }
168
169 async updateViewCount(id: string): Promise<void> {
170 await db
171 .update(repairGuides)
172 .set({ viewCount: sql`${repairGuides.viewCount} + 1` })
173 .where(eq(repairGuides.id, id));
174 }
175
176 async updateDownloadCount(id: string): Promise<void> {
177 await db
178 .update(repairGuides)
179 .set({ downloadCount: sql`${repairGuides.downloadCount} + 1` })
180 .where(eq(repairGuides.id, id));
181 }
182
183 async toggleBookmark(id: string): Promise<RepairGuide | undefined> {
184 const [guide] = await db
185 .update(repairGuides)
186 .set({ isBookmarked: sql`NOT ${repairGuides.isBookmarked}` })
187 .where(eq(repairGuides.id, id))
188 .returning();
189 return guide;
190 }
191
192 async searchRepairGuides(query: string): Promise<RepairGuide[]> {
193 const searchTerm = `%${query.toLowerCase()}%`;
194 return await db
195 .select()
196 .from(repairGuides)
197 .where(
198 or(
199 like(repairGuides.title, searchTerm),
200 like(repairGuides.description, searchTerm),
201 like(repairGuides.category, searchTerm)
202 )
203 );
204 }
205
206 // Troubleshooting Flows operations
207 async getTroubleshootingFlows(): Promise<TroubleshootingFlow[]> {
208 return await db.select().from(troubleshootingFlows);
209 }
210
211 async getTroubleshootingFlow(id: string): Promise<TroubleshootingFlow | undefined> {
212 const [flow] = await db.select().from(troubleshootingFlows).where(eq(troubleshootingFlows.id, id));
213 return flow;
214 }
215
216 async createTroubleshootingFlow(flow: InsertTroubleshootingFlow): Promise<TroubleshootingFlow> {
217 const [newFlow] = await db.insert(troubleshootingFlows).values(flow).returning();
218 return newFlow;
219 }
220
221 // Device Components operations
222 async getDeviceComponents(deviceType?: string): Promise<DeviceComponent[]> {
223 if (deviceType) {
224 return await db.select().from(deviceComponents).where(eq(deviceComponents.deviceType, deviceType));
225 }
226 return await db.select().from(deviceComponents);
227 }
228
229 async getDeviceComponent(id: string): Promise<DeviceComponent | undefined> {
230 const [component] = await db.select().from(deviceComponents).where(eq(deviceComponents.id, id));
231 return component;
232 }
233
234 async createDeviceComponent(component: InsertDeviceComponent): Promise<DeviceComponent> {
235 const [newComponent] = await db.insert(deviceComponents).values(component).returning();
236 return newComponent;
237 }
238
239 // Device Brands and Models
240 async getDeviceBrands(deviceType?: string): Promise<DeviceBrand[]> {
241 const query = db.select().from(deviceBrands);
242 if (deviceType) {
243 return await query.where(eq(deviceBrands.deviceType, deviceType)).orderBy(sql`${deviceBrands.popularity} DESC`);
244 }
245 return await query.orderBy(sql`${deviceBrands.popularity} DESC`);
246 }
247
248 async getDeviceModels(brandId?: string, deviceType?: string): Promise<DeviceModel[]> {
249 let query = db.select().from(deviceModels);
250
251 if (brandId) {
252 query = query.where(eq(deviceModels.brandId, brandId));
253 }
254
255 return await query.orderBy(sql`${deviceModels.year} DESC, ${deviceModels.name} ASC`);
256 }
257
258 async getDeviceModel(id: string): Promise<DeviceModel | undefined> {
259 const [model] = await db.select().from(deviceModels).where(eq(deviceModels.id, id));
260 return model;
261 }
262
263 async getModelsByBrand(brandId: string): Promise<DeviceModel[]> {
264 return await db.select()
265 .from(deviceModels)
266 .where(eq(deviceModels.brandId, brandId))
267 .orderBy(sql`${deviceModels.year} DESC, ${deviceModels.name} ASC`);
268 }
269
270 async searchDeviceModels(query: string, deviceType?: string): Promise<DeviceModel[]> {
271 return await db.select()
272 .from(deviceModels)
273 .where(
274 or(
275 like(deviceModels.name, `%${query}%`),
276 like(deviceModels.series, `%${query}%`)
277 )
278 )
279 .orderBy(sql`${deviceModels.guideCount} DESC`);
280 }
281
282 // Guide Compatibility
283 async getCompatibleGuides(modelId: string): Promise<RepairGuide[]> {
284 return await db.select()
285 .from(repairGuides)
286 .innerJoin(guideCompatibility, eq(repairGuides.id, guideCompatibility.guideId))
287 .where(
288 and(
289 eq(guideCompatibility.modelId, modelId),
290 eq(guideCompatibility.compatibility, 'compatible')
291 )
292 )
293 .orderBy(sql`${repairGuides.viewCount} DESC`);
294 }
295
296 async getModelCompatibility(guideId: string): Promise<DeviceModel[]> {
297 return await db.select()
298 .from(deviceModels)
299 .innerJoin(guideCompatibility, eq(deviceModels.id, guideCompatibility.modelId))
300 .where(eq(guideCompatibility.guideId, guideId))
301 .orderBy(sql`${deviceModels.name} ASC`);
302 }
303
304 async createUserGuide(guide: InsertRepairGuide): Promise<RepairGuide> {
305 const [createdGuide] = await db
306 .insert(repairGuides)
307 .values(guide)
308 .returning();
309 return createdGuide;
310 }
311 }
312
313 export const storage = new DatabaseStorage();