🚀 Final: Fix stats, staff list, settings profile, and logout redirect

This commit is contained in:
Hamza-Ayed
2026-04-19 15:36:45 +03:00
parent 946c7db96c
commit 3ae3f1d797
5 changed files with 43 additions and 11 deletions

View File

@@ -62,6 +62,16 @@ export class AuthController {
return this.authService.logout(user.id); return this.authService.logout(user.id);
} }
/**
* الملف الشخصي الحالي والبيانات الأساسية
*/
@UseGuards(JwtAuthGuard)
@Get('me')
@HttpCode(HttpStatus.OK)
async me(@CurrentUser() user: any) {
return this.authService.getMe(user.id);
}
/** /**
* الملف الشخصي * الملف الشخصي
*/ */

View File

@@ -179,6 +179,29 @@ export class AuthService {
}; };
} }
/**
* الحصول على بيانات المستخدم والاشتراك الحالي
*/
async getMe(userId: string) {
const user = await this.dataSource.getRepository(User).findOne({
where: { id: userId },
relations: ['tenant'],
});
if (!user) throw new UnauthorizedException();
return {
user: {
id: user.id,
name: user.name,
email: user.email,
role: user.role,
tenantId: user.tenant_id,
},
tenant: user.tenant,
};
}
/** /**
* تسجيل خروج * تسجيل خروج
*/ */

View File

@@ -22,13 +22,6 @@ export class DashboardService {
where: { tenant_id: tenantId, status: InvoiceStatus.APPROVED }, where: { tenant_id: tenantId, status: InvoiceStatus.APPROVED },
}); });
const pendingInvoices = await this.invoiceRepository.count({
where: {
tenant_id: tenantId,
status: Buffer.from('approved').toString() === InvoiceStatus.APPROVED ? InvoiceStatus.UPLOADED : InvoiceStatus.UPLOADED // wait, using In operator is better
},
});
// Using QueryBuilder for better control // Using QueryBuilder for better control
const statuses = await this.invoiceRepository const statuses = await this.invoiceRepository
.createQueryBuilder('invoice') .createQueryBuilder('invoice')

View File

@@ -4,7 +4,7 @@
* ════════════════════════════════════════════════════════════ * ════════════════════════════════════════════════════════════
*/ */
import { NavLink } from 'react-router-dom'; import { NavLink, useNavigate } from 'react-router-dom';
import { import {
LayoutDashboard, LayoutDashboard,
FileText, FileText,
@@ -24,8 +24,14 @@ const menuItems = [
]; ];
export const Sidebar = () => { export const Sidebar = () => {
const navigate = useNavigate();
const clearAuth = useAuthStore((state) => state.clearAuth); const clearAuth = useAuthStore((state) => state.clearAuth);
const handleLogout = () => {
clearAuth();
navigate('/login');
};
return ( return (
<aside className="w-64 h-screen glass border-l border-slate-200 sticky top-0 flex flex-col p-4"> <aside className="w-64 h-screen glass border-l border-slate-200 sticky top-0 flex flex-col p-4">
<div className="flex items-center gap-3 px-2 py-6"> <div className="flex items-center gap-3 px-2 py-6">
@@ -58,7 +64,7 @@ export const Sidebar = () => {
<div className="pt-4 border-t border-slate-100"> <div className="pt-4 border-t border-slate-100">
<button <button
onClick={clearAuth} onClick={handleLogout}
className="flex items-center gap-3 px-4 py-3 w-full rounded-xl text-red-500 hover:bg-red-50 transition-all group" className="flex items-center gap-3 px-4 py-3 w-full rounded-xl text-red-500 hover:bg-red-50 transition-all group"
> >
<LogOut className="w-5 h-5 group-hover:-translate-x-1 transition-transform" /> <LogOut className="w-5 h-5 group-hover:-translate-x-1 transition-transform" />

View File

@@ -40,7 +40,7 @@ export const StaffPage = () => {
e.preventDefault(); e.preventDefault();
try { try {
await apiClient.post('/users', { await apiClient.post('/users', {
full_name: fullName, name: fullName,
email, email,
password, password,
role role
@@ -108,7 +108,7 @@ export const StaffPage = () => {
</div> </div>
</div> </div>
<h3 className="text-xl font-bold text-slate-900 mb-1">{member.full_name}</h3> <h3 className="text-xl font-bold text-slate-900 mb-1">{member.name}</h3>
<div className="flex items-center gap-2 mb-6"> <div className="flex items-center gap-2 mb-6">
<span className={`text-[10px] font-black uppercase tracking-widest px-2 py-0.5 rounded-md ${ <span className={`text-[10px] font-black uppercase tracking-widest px-2 py-0.5 rounded-md ${
member.role === 'admin' ? 'bg-indigo-50 text-indigo-600' : 'bg-slate-50 text-slate-600' member.role === 'admin' ? 'bg-indigo-50 text-indigo-600' : 'bg-slate-50 text-slate-600'