feat: Implement authentication checks for profile actions and user layout, and add presigned URL fetching for file viewing.

This commit is contained in:
pradeepkumar
2026-01-29 00:02:59 +05:30
parent 4ffd6305b1
commit b41bd8a3eb
9 changed files with 243 additions and 40 deletions

View File

@@ -444,6 +444,7 @@ function RangeSlider({ field, value, onChange }: RangeSliderProps) {
// File Upload Types
interface UploadedFile {
id: string;
key?: string; // S3 key for fetching presigned URL
name: string;
size: number;
type: string;
@@ -459,6 +460,12 @@ interface UploadingFile {
error?: string;
}
// Map to store presigned URLs by file ID
interface FileWithPresignedUrl extends UploadedFile {
presignedUrl?: string;
isLoadingUrl?: boolean;
}
// File Upload Component
interface FileUploadProps {
field: ProfileField;
@@ -471,6 +478,8 @@ function FileUpload({ field, fieldSlug, value, onChange }: FileUploadProps) {
const fileInputRef = useRef<HTMLInputElement>(null);
const [isDragging, setIsDragging] = useState(false);
const [uploadingFiles, setUploadingFiles] = useState<UploadingFile[]>([]);
const [presignedUrls, setPresignedUrls] = useState<Record<string, string>>({});
const [loadingUrls, setLoadingUrls] = useState<Record<string, boolean>>({});
// Get allowed formats from field config or use defaults
const allowedFormats = field.validation?.allowedFormats || ['PDF', 'DOCX', 'JPG', 'PNG'];
@@ -631,6 +640,42 @@ function FileUpload({ field, fieldSlug, value, onChange }: FileUploadProps) {
fileInputRef.current?.click();
};
const handleViewFile = async (file: UploadedFile) => {
// Check if we already have a presigned URL
if (presignedUrls[file.id]) {
window.open(presignedUrls[file.id], '_blank');
return;
}
// Get the key - either from file.key, file.id, or file.url if it's an S3 key
const fileKey = file.key || file.id || file.url;
// If the URL is already a full URL (http/https), just open it directly
if (fileKey.startsWith('http://') || fileKey.startsWith('https://')) {
window.open(fileKey, '_blank');
return;
}
// Set loading state
setLoadingUrls(prev => ({ ...prev, [file.id]: true }));
try {
const { uploadService } = await import('@/services/upload.service');
const presignedUrl = await uploadService.getPresignedDownloadUrl(fileKey);
// Store for future use
setPresignedUrls(prev => ({ ...prev, [file.id]: presignedUrl }));
// Open the file
window.open(presignedUrl, '_blank');
} catch (error) {
console.error('Failed to get presigned URL:', error);
alert('Failed to open file. Please try again.');
} finally {
setLoadingUrls(prev => ({ ...prev, [file.id]: false }));
}
};
const isUploading = uploadingFiles.length > 0;
return (
@@ -744,20 +789,14 @@ function FileUpload({ field, fieldSlug, value, onChange }: FileUploadProps) {
>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
{file.url ? (
<a
href={file.url}
target="_blank"
rel="noopener noreferrer"
className="text-[14px] font-serif text-[#E58625] hover:underline truncate"
>
{file.name}
</a>
) : (
<span className="text-[14px] font-serif text-[#00293D] truncate">
{file.name}
</span>
)}
<button
type="button"
onClick={() => handleViewFile(file)}
disabled={loadingUrls[file.id]}
className="text-[14px] font-serif text-[#E58625] hover:underline truncate text-left disabled:opacity-50"
>
{loadingUrls[file.id] ? 'Loading...' : file.name}
</button>
<button
type="button"
onClick={() => handleRemoveFile(file.id)}