🚀 Hotfixes: inline PDF preview and instant profile update in UI

This commit is contained in:
Hamza-Ayed
2026-04-22 17:15:43 +03:00
parent 4c2fd7bba5
commit 7e0e271be2
3 changed files with 31 additions and 1 deletions

View File

@@ -18,7 +18,9 @@ import {
UploadedFile,
UseInterceptors,
ParseUUIDPipe,
Res,
} from '@nestjs/common';
import { Response } from 'express';
import { FileInterceptor } from '@nestjs/platform-express';
import { InvoicesService } from './invoice.service';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
@@ -111,7 +113,25 @@ export class InvoicesController {
async getFile(
@CurrentUser() user: any,
@Param('id', ParseUUIDPipe) id: string,
@Res({ passthrough: true }) res: Response,
) {
return this.invoicesService.getFile(user.tenantId, id);
const streamableFile = await this.invoicesService.getFile(user.tenantId, id);
// We need to determine the content type to ensure it opens inline in the browser (iframe)
// We can fetch the invoice details first to get the extension.
const invoice = await this.invoicesService.findOne(user.tenantId, id);
let mimeType = 'application/pdf'; // Default fallback
if (invoice.original_file_path) {
const ext = invoice.original_file_path.split('.').pop()?.toLowerCase();
if (ext === 'jpg' || ext === 'jpeg') mimeType = 'image/jpeg';
else if (ext === 'png') mimeType = 'image/png';
}
res.set({
'Content-Type': mimeType,
'Content-Disposition': 'inline', // This forces the browser to display it instead of downloading
});
return streamableFile;
}
}

View File

@@ -21,6 +21,7 @@ import {
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import apiClient from '../../api/client';
import { useAuthStore } from '../../store/authStore';
export const SettingsPage = () => {
const [activeTab, setActiveTab] = useState('profile');
@@ -37,6 +38,8 @@ export const SettingsPage = () => {
language: 'العربية'
});
const updateUser = useAuthStore((state) => state.updateUser);
useEffect(() => {
const fetchProfile = async () => {
try {
@@ -62,6 +65,7 @@ export const SettingsPage = () => {
setIsSaving(true);
try {
await apiClient.post('/users/profile', formData);
updateUser({ name: formData.name });
setShowSuccess(true);
setTimeout(() => setShowSuccess(false), 3000);
} catch (err) {

View File

@@ -20,6 +20,7 @@ interface AuthState {
isAuthenticated: boolean;
setAuth: (user: User, token: string) => void;
clearAuth: () => void;
updateUser: (data: Partial<User>) => void;
}
export const useAuthStore = create<AuthState>()(
@@ -35,6 +36,11 @@ export const useAuthStore = create<AuthState>()(
localStorage.removeItem('access_token');
set({ user: null, isAuthenticated: false });
},
updateUser: (data) => {
set((state) => ({
user: state.user ? { ...state.user, ...data } : null
}));
},
}),
{
name: 'musadaq-auth-storage',