1+ import { Request , Response } from 'express' ;
2+ import { asyncHandler } from '../utils/asyncHandler.js' ;
3+ import { sendSuccess , sendBadRequest , sendNotFound , sendPaginatedSuccess } from '../utils/apiResponses.js' ;
4+ import { validateLocationLogo } from '../schemas/locationLogoSchema.js' ;
5+ import LocationLogo from '../models/locationLogosModel.js' ;
6+ import { deleteFile } from '../middleware/uploadMiddleware.js' ;
7+
8+ // @desc Get all location logos with optional filtering
9+ // @route GET /api/location-logos
10+ // @access Private
11+ export const getLocationLogos = asyncHandler ( async ( req : Request , res : Response ) => {
12+ const {
13+ location,
14+ locations, // Comma-separated list for location filtering
15+ search,
16+ page = 1 ,
17+ limit = 9 ,
18+ sortBy = 'DocumentModifiedDate' ,
19+ sortOrder = 'desc'
20+ } = req . query ;
21+
22+ const query : any = { } ;
23+ const conditions : any [ ] = [ ] ;
24+
25+ // Apply search filter
26+ if ( search && typeof search === 'string' ) {
27+ conditions . push ( {
28+ $or : [
29+ { DisplayName : { $regex : search . trim ( ) , $options : 'i' } }
30+ ]
31+ } ) ;
32+ }
33+
34+ // Apply location filter
35+ if ( locations && typeof locations === 'string' ) {
36+ const locationArray = locations . split ( ',' ) . map ( loc => loc . trim ( ) ) . filter ( Boolean ) ;
37+ if ( locationArray . length > 0 ) {
38+ conditions . push ( { LocationSlug : { $in : locationArray } } ) ;
39+ }
40+ } else if ( location && typeof location === 'string' ) {
41+ conditions . push ( { LocationSlug : location } ) ;
42+ }
43+
44+ // Combine all conditions with AND logic
45+ if ( conditions . length > 0 ) {
46+ query . $and = conditions ;
47+ }
48+
49+ // Pagination
50+ const skip = ( Number ( page ) - 1 ) * Number ( limit ) ;
51+
52+ // Sort options
53+ const sortOptions : any = { } ;
54+ sortOptions [ sortBy as string ] = sortOrder === 'desc' ? - 1 : 1 ;
55+
56+ const logos = await LocationLogo . find ( query )
57+ . sort ( sortOptions )
58+ . skip ( skip )
59+ . limit ( Number ( limit ) )
60+ . lean ( ) ;
61+
62+ // Get total count using the same query
63+ const total = await LocationLogo . countDocuments ( query ) ;
64+
65+ return sendPaginatedSuccess ( res , logos , {
66+ page : Number ( page ) ,
67+ limit : Number ( limit ) ,
68+ total,
69+ pages : Math . ceil ( total / Number ( limit ) )
70+ } ) ;
71+ } ) ;
72+
73+ // @desc Get single location logo by ID
74+ // @route GET /api/location-logos/:id
75+ // @access Private
76+ export const getLocationLogoById = asyncHandler ( async ( req : Request , res : Response ) => {
77+ const logo = await LocationLogo . findById ( req . params . id ) ;
78+
79+ if ( ! logo ) {
80+ return sendNotFound ( res , 'Location logo not found' ) ;
81+ }
82+
83+ return sendSuccess ( res , logo ) ;
84+ } ) ;
85+
86+
87+ // @desc Create location logo
88+ // @route POST /api/location-logos
89+ // @access Private
90+ export const createLocationLogo = asyncHandler ( async ( req : Request , res : Response ) => {
91+ // Extract uploaded file URL from req
92+ let logoPath = '' ;
93+ if ( req . body . LogoPath ) {
94+ logoPath = req . body . LogoPath ;
95+ }
96+
97+ const logoData = {
98+ ...req . body ,
99+ LogoPath : logoPath ,
100+ CreatedBy : req . user ?. id || 'system'
101+ } ;
102+
103+ // Validate logo data
104+ const validation = validateLocationLogo ( logoData ) ;
105+ if ( ! validation . success ) {
106+ return sendBadRequest ( res , 'Validation failed' ) ;
107+ }
108+
109+ // Create location logo
110+ const logo = await LocationLogo . create ( logoData ) ;
111+
112+ return sendSuccess ( res , logo , 'Location logo created successfully' ) ;
113+ } ) ;
114+
115+ // @desc Update location logo
116+ // @route PUT /api/location-logos/:id
117+ // @access Private
118+ export const updateLocationLogo = asyncHandler ( async ( req : Request , res : Response ) => {
119+ const { id } = req . params ;
120+
121+ // Get existing location logo
122+ const existingLogo = await LocationLogo . findById ( id ) ;
123+
124+ if ( ! existingLogo ) {
125+ return sendNotFound ( res , 'Location logo not found' ) ;
126+ }
127+
128+ // Store old logo path for cleanup
129+ const oldLogoPath = existingLogo . LogoPath ;
130+
131+ // Extract uploaded file URL from req
132+ let logoPath = existingLogo . LogoPath ;
133+ if ( req . body . LogoPath && req . body . LogoPath !== existingLogo . LogoPath ) {
134+ logoPath = req . body . LogoPath ;
135+ }
136+
137+ const logoData = {
138+ ...req . body ,
139+ LogoPath : logoPath ,
140+ DocumentModifiedDate : new Date ( )
141+ } ;
142+
143+ // Validate logo data
144+ const validation = validateLocationLogo ( logoData ) ;
145+ if ( ! validation . success ) {
146+ return sendBadRequest ( res , 'Validation failed' ) ;
147+ }
148+
149+ // Update location logo
150+ const updatedLogo = await LocationLogo . findByIdAndUpdate (
151+ id ,
152+ logoData ,
153+ { new : true , runValidators : true }
154+ ) ;
155+
156+ // Cleanup old logo file if it was replaced
157+ if ( logoPath !== oldLogoPath && oldLogoPath ) {
158+ try {
159+ await deleteFile ( oldLogoPath ) ;
160+ console . log ( `Deleted old logo file: ${ oldLogoPath } ` ) ;
161+ } catch ( error ) {
162+ console . error ( `Failed to delete old logo file: ${ oldLogoPath } ` , error ) ;
163+ }
164+ }
165+
166+ return sendSuccess ( res , updatedLogo , 'Location logo updated successfully' ) ;
167+ } ) ;
168+
169+ // @desc Delete location logo
170+ // @route DELETE /api/location-logos/:id
171+ // @access Private
172+ export const deleteLocationLogo = asyncHandler ( async ( req : Request , res : Response ) => {
173+ const { id } = req . params ;
174+
175+ const logo = await LocationLogo . findById ( id ) ;
176+
177+ if ( ! logo ) {
178+ return sendNotFound ( res , 'Location logo not found' ) ;
179+ }
180+
181+ // Store logo path for cleanup
182+ const logoPath = logo . LogoPath ;
183+
184+ // Delete from database
185+ await LocationLogo . findByIdAndDelete ( id ) ;
186+
187+ // Delete logo file from storage
188+ if ( logoPath ) {
189+ try {
190+ await deleteFile ( logoPath ) ;
191+ console . log ( `Deleted logo file: ${ logoPath } ` ) ;
192+ } catch ( error ) {
193+ console . error ( `Failed to delete logo file: ${ logoPath } ` , error ) ;
194+ }
195+ }
196+
197+ return sendSuccess ( res , null , 'Location logo deleted successfully' ) ;
198+ } ) ;
0 commit comments