Skip to content

Commit 522d49c

Browse files
Merge pull request #68 from InternPulse/feat/global-search
global search
2 parents b8d3d5c + 41a3740 commit 522d49c

4 files changed

Lines changed: 204 additions & 72 deletions

File tree

src/controllers/facility.controller.ts

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ declare global {
77
decodeuser?: any;
88
}
99
}
10-
};
10+
}
1111

1212
import {
1313
createFacility,
@@ -17,11 +17,17 @@ import {
1717
getAllFacility_ByFiltering,
1818
getFacilitiesByOperator,
1919
updateFacilityCapacity,
20+
searchFacilities,
2021
} from "../services/db/facility.service";
2122
import { StatusCodes } from "http-status-codes";
22-
import { BadRequestError, NotFoundError, UnauthorizedError } from "../errors/errors";
23+
import {
24+
BadRequestError,
25+
NotFoundError,
26+
UnauthorizedError,
27+
} from "../errors/errors";
2328
import { PrismaClient } from "@prisma/client";
2429
import { deleteImageFromCloudinary } from "../services/cloudinary.service";
30+
import { FacilityFilterOptions } from "../types/types";
2531
const prisma = new PrismaClient();
2632

2733
export const addFacility = async (
@@ -30,7 +36,10 @@ export const addFacility = async (
3036
next: NextFunction
3137
) => {
3238
try {
33-
const facility = await createFacility({...req.body, operatorId: req.currentUser.operatorId});
39+
const facility = await createFacility({
40+
...req.body,
41+
operatorId: req.currentUser.operatorId,
42+
});
3443

3544
res.status(StatusCodes.CREATED).json({
3645
message: "Facility created successfully",
@@ -41,7 +50,6 @@ export const addFacility = async (
4150
}
4251
};
4352

44-
4553
export const deleteFacilityImage = async (
4654
req: Request,
4755
res: Response,
@@ -57,9 +65,9 @@ export const deleteFacilityImage = async (
5765
});
5866
if (!facility) {
5967
throw new NotFoundError({
60-
message: 'Error deleting facility image',
61-
from: 'deleteFacilityImage()',
62-
cause: 'Facility not found'
68+
message: "Error deleting facility image",
69+
from: "deleteFacilityImage()",
70+
cause: "Facility not found",
6371
});
6472
}
6573

@@ -76,27 +84,33 @@ export const deleteFacilityImage = async (
7684
message: "Image deleted successfully",
7785
});
7886
return;
79-
8087
} catch (error) {
8188
next(error);
8289
}
8390
};
8491

85-
export const getFacility = async (req: Request, res: Response, next: NextFunction) => {
92+
export const getFacility = async (
93+
req: Request,
94+
res: Response,
95+
next: NextFunction
96+
) => {
8697
try {
8798
const facilityId = BigInt(req.params.facilityId);
88-
const facility = await getFacilityById(facilityId );
89-
res.status(StatusCodes.OK).json({
90-
message: "Facility fetch successful",
91-
facility: facility
99+
const facility = await getFacilityById(facilityId);
100+
res.status(StatusCodes.OK).json({
101+
message: "Facility fetch successful",
102+
facility: facility,
92103
});
93-
94-
} catch(error) {
104+
} catch (error) {
95105
next(error);
96106
}
97107
};
98108

99-
export const updateFacility = async (req: Request, res: Response, next: NextFunction) => {
109+
export const updateFacility = async (
110+
req: Request,
111+
res: Response,
112+
next: NextFunction
113+
) => {
100114
try {
101115
const facility = req.facility; // already validated by isFacilityOwner
102116
const updateData = req.body;
@@ -112,7 +126,6 @@ export const updateFacility = async (req: Request, res: Response, next: NextFunc
112126
}
113127
};
114128

115-
116129
export const deleteFacility = async (
117130
req: Request,
118131
res: Response,
@@ -169,7 +182,7 @@ export const getAllFacilityByFiltering = async (
169182
message: `Invalid type '${filters.type}'. Must be one of ${validTypes.join(", ")}`,
170183
from: "getAllFacility",
171184
});
172-
};
185+
}
173186

174187
const { role, operatorId } = req.currentUser; // if user is a farmer or operator, to enable the filtering.
175188
const result = await getAllFacility_ByFiltering(filters, role, operatorId);
@@ -178,20 +191,17 @@ export const getAllFacilityByFiltering = async (
178191
message: "Facilities fetched successfully",
179192
...result,
180193
});
181-
182194
} catch (error) {
183195
next(error);
184196
}
185197
};
186198

187-
188199
export const getFacilitiesByOperatorController = async (
189200
req: Request,
190201
res: Response,
191202
next: NextFunction
192203
) => {
193204
try {
194-
195205
const operatorId = BigInt(req.operator?.id); // Get from isAuthorisedMiddleware
196206
if (!operatorId) {
197207
throw new UnauthorizedError({
@@ -210,7 +220,7 @@ export const getFacilitiesByOperatorController = async (
210220
});
211221

212222
if (result.facilities.length === 0) {
213-
res.status(StatusCodes.OK).json({
223+
res.status(StatusCodes.OK).json({
214224
message: "You don't own any facilities yet",
215225
facilities: [],
216226
pagination: result.pagination,
@@ -237,7 +247,7 @@ export const updateCapacity = async (
237247
const parsedCapacity = parseInt(capacity, 10);
238248

239249
if (!parsedCapacity || isNaN(parsedCapacity) || parsedCapacity < 0) {
240-
throw new BadRequestError({
250+
throw new BadRequestError({
241251
message: "Capacity musst be a positive number",
242252
from: "updateCapacity",
243253
});
@@ -256,3 +266,54 @@ export const updateCapacity = async (
256266
next(error);
257267
}
258268
};
269+
270+
export const globalFacilitySearch = async (
271+
req: Request,
272+
res: Response,
273+
next: NextFunction
274+
) => {
275+
try {
276+
const {
277+
location,
278+
type,
279+
available,
280+
operatorName,
281+
minPrice,
282+
maxPrice,
283+
page = "1",
284+
limit = "10",
285+
} = req.query;
286+
287+
const allowedTypes = [
288+
"DRYER",
289+
"STORAGE",
290+
"PROCESSING",
291+
"COLDROOM",
292+
"OTHER",
293+
] as const;
294+
type FacilityType = (typeof allowedTypes)[number];
295+
296+
const filters: FacilityFilterOptions = {
297+
location: location as string,
298+
type: allowedTypes.includes(type as FacilityType)
299+
? (type as FacilityType)
300+
: undefined,
301+
available:
302+
available === "true" ? true : available === "false" ? false : undefined,
303+
operatorName: operatorName as string,
304+
minPrice: minPrice ? Number(minPrice) : undefined,
305+
maxPrice: maxPrice ? Number(maxPrice) : undefined,
306+
page: Number(page),
307+
limit: Number(limit),
308+
};
309+
310+
const response = await searchFacilities(filters);
311+
312+
res.status(200).json({
313+
message: "Facilities fetched successfully",
314+
data: response,
315+
});
316+
} catch (error) {
317+
next(error);
318+
}
319+
};

src/routes/facility.routes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import express from 'express';
22
import { facilityValidator } from '../utils/validateFacility';
33
import { verifyAuth } from '../middlewares/authenticate.middleware';
44
import { isAuthorizedOperator, isOperator, isFacilityOwner } from '../middlewares/authorization.middlewares';
5-
import { addFacility, getFacility, updateFacility, getAllFacilityByFiltering, deleteFacility, updateCapacity , deleteFacilityImage, getFacilitiesByOperatorController } from '../controllers/facility.controller';
5+
import { addFacility, getFacility, updateFacility, getAllFacilityByFiltering, deleteFacility, updateCapacity , deleteFacilityImage, getFacilitiesByOperatorController, globalFacilitySearch } from '../controllers/facility.controller';
66
import { upload } from '../config/config.cloudinary';
77
import { uploadFacilityImage } from '../controllers/cloudinary.controller';
88

@@ -11,6 +11,7 @@ const router = express.Router();
1111
//Ideally facilityId should be id
1212
router.post('/', verifyAuth, facilityValidator, addFacility);
1313
router.get('/', verifyAuth, getAllFacilityByFiltering); //Allows filtering and no filtering
14+
router.get('/search', verifyAuth, globalFacilitySearch)
1415
router.get('/all', verifyAuth, isAuthorizedOperator, getFacilitiesByOperatorController);
1516
router.post('/images', verifyAuth, isOperator, upload.array('images', 5), uploadFacilityImage);
1617

0 commit comments

Comments
 (0)