182 lines
5.2 KiB
TypeScript
182 lines
5.2 KiB
TypeScript
import { processImage, validateImageFile, generateUniqueFileName, ProcessedImage } from '../utils/imageUtils';
|
|
import { secureApi } from './secureApi';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
|
|
export interface StoredImage {
|
|
id: string;
|
|
dataUrl: string;
|
|
filename: string;
|
|
originalSize: number;
|
|
compressedSize: number;
|
|
uploadedAt: number;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
/**
|
|
* Upload and store an image through secure API
|
|
* @param file - The image file to upload
|
|
* @param collectionName - Collection name (e.g., 'company-logos')
|
|
* @param documentId - Document ID (e.g., orgId)
|
|
* @param orgId - Organization ID
|
|
* @param userId - User ID for authentication
|
|
* @param maxWidth - Maximum width for resizing (default: 128)
|
|
* @param maxHeight - Maximum height for resizing (default: 128)
|
|
* @returns Promise with stored image data
|
|
*/
|
|
export const uploadImage = async (
|
|
file: File,
|
|
collectionName: string,
|
|
documentId: string,
|
|
orgId: string,
|
|
userId: string,
|
|
maxWidth: number = 128,
|
|
maxHeight: number = 128
|
|
): Promise<StoredImage> => {
|
|
// Validate the image file
|
|
const validation = validateImageFile(file);
|
|
if (!validation.valid) {
|
|
throw new Error(validation.error);
|
|
}
|
|
|
|
// Process the image
|
|
const processedImage: ProcessedImage = await processImage(file, maxWidth, maxHeight);
|
|
|
|
// Generate unique filename
|
|
const filename = generateUniqueFileName(file.name, 'logo');
|
|
|
|
// Create image data to upload
|
|
const imageData = {
|
|
collectionName,
|
|
documentId,
|
|
dataUrl: processedImage.dataUrl,
|
|
filename,
|
|
originalSize: processedImage.originalSize,
|
|
compressedSize: processedImage.compressedSize,
|
|
width: processedImage.width,
|
|
height: processedImage.height,
|
|
};
|
|
|
|
try {
|
|
const result = await secureApi.uploadImage(orgId, userId, imageData);
|
|
|
|
if (!result.success) {
|
|
throw new Error('Failed to upload image');
|
|
}
|
|
|
|
return {
|
|
id: result.imageId,
|
|
dataUrl: processedImage.dataUrl,
|
|
filename,
|
|
originalSize: processedImage.originalSize,
|
|
compressedSize: processedImage.compressedSize,
|
|
uploadedAt: Date.now(),
|
|
width: processedImage.width,
|
|
height: processedImage.height,
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to upload image through secure API:', error);
|
|
throw new Error('Failed to upload image');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Retrieve an image through secure API
|
|
* @param collectionName - Collection name
|
|
* @param documentId - Document ID
|
|
* @param orgId - Organization ID
|
|
* @param userId - User ID for authentication
|
|
* @returns Promise with stored image data or null if not found
|
|
*/
|
|
export const getImage = async (
|
|
collectionName: string,
|
|
documentId: string,
|
|
orgId: string,
|
|
userId: string
|
|
): Promise<StoredImage | null> => {
|
|
try {
|
|
const result = await secureApi.getImage(orgId, userId, collectionName, documentId);
|
|
|
|
return result; // getImage already returns StoredImage | null
|
|
} catch (error) {
|
|
console.error('Failed to retrieve image through secure API:', error);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Delete an image through secure API
|
|
* @param collectionName - Collection name
|
|
* @param documentId - Document ID
|
|
* @param orgId - Organization ID
|
|
* @param userId - User ID for authentication
|
|
* @returns Promise indicating success
|
|
*/
|
|
export const deleteImage = async (
|
|
collectionName: string,
|
|
documentId: string,
|
|
orgId: string,
|
|
userId: string
|
|
): Promise<boolean> => {
|
|
try {
|
|
const result = await secureApi.deleteImage(orgId, userId, collectionName, documentId);
|
|
|
|
return result; // deleteImage already returns boolean
|
|
} catch (error) {
|
|
console.error('Failed to delete image through secure API:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Company-specific image upload (convenience function)
|
|
* Requires authentication context to get userId
|
|
*/
|
|
export const uploadCompanyLogo = async (
|
|
file: File,
|
|
orgId: string,
|
|
userId: string
|
|
): Promise<StoredImage> => {
|
|
return uploadImage(file, 'company-logos', orgId, orgId, userId, 128, 128);
|
|
};
|
|
|
|
/**
|
|
* Get company logo (convenience function)
|
|
* Requires authentication context to get userId
|
|
*/
|
|
export const getCompanyLogo = async (
|
|
orgId: string,
|
|
userId: string
|
|
): Promise<StoredImage | null> => {
|
|
return getImage('company-logos', orgId, orgId, userId);
|
|
};
|
|
|
|
/**
|
|
* Delete company logo (convenience function)
|
|
* Requires authentication context to get userId
|
|
*/
|
|
export const deleteCompanyLogo = async (
|
|
orgId: string,
|
|
userId: string
|
|
): Promise<boolean> => {
|
|
return deleteImage('company-logos', orgId, orgId, userId);
|
|
};
|
|
|
|
/**
|
|
* Hook-based convenience functions that automatically get userId from auth context
|
|
* Use these in React components where useAuth is available
|
|
*/
|
|
export const useImageStorage = () => {
|
|
// Note: This would need to be implemented in a React component context
|
|
// where useAuth() is available. For now, we provide the functions that require
|
|
// explicit userId parameter.
|
|
|
|
return {
|
|
uploadImage,
|
|
getImage,
|
|
deleteImage,
|
|
uploadCompanyLogo,
|
|
getCompanyLogo,
|
|
deleteCompanyLogo,
|
|
};
|
|
}; |