RAKAEZ
Routes & State Management

خريطة المسارات وإدارة الحالة

Angular Routes · NgRx Stores · Folder Structure · للفريق التقني

١ · Angular Routes Map

خريطة كل المسارات في لوحة التحكم

٤٧ مسار رئيسي + Lazy Modules + Guards

/ (Root)
📁 /auth (Public)
/login
صفحة تسجيل الدخول
PUBLIC
LoginPage
/forgot-password
استعادة كلمة المرور
PUBLIC
ForgotPwd
/reset-password/:token
إعادة التعيين
PUBLIC
ResetPwd
/otp-verify
التحقق من الـ OTP
PUBLIC
OtpPage
📁 /dashboard (Auth Guard)
/dashboard
النظرة العامة + KPIs
AUTH
Overview
/dashboard/analytics
التحليلات المتقدمة
RBAC
Analytics
📁 /projects (Lazy Module)
/projects
قائمة المشاريع
RBAC
List
/projects/new
إنشاء مشروع جديد
RBAC
Create
/projects/:id
تفاصيل المشروع
RBAC
Details
/projects/:id/edit
تعديل المشروع
RBAC
Edit
/projects/:id/timeline
الجدول الزمني (Gantt)
RBAC
Timeline
/projects/:id/budget
الميزانية
RBAC
Budget
/projects/:id/files
ملفات المشروع
RBAC
Files
/projects/:id/team
فريق المشروع
RBAC
Team
📁 /planning (Lazy Module) ⭐ NEW
/planning
لوحة التخطيط
RBAC
Dashboard
/planning/schedule/:projectId
جدول مشروع أسبوعي
RBAC
Schedule
/planning/items/:id
تفاصيل بند
RBAC
ItemDetail
/planning/items/:id/quality
فحص الجودة
RBAC
Quality
/planning/sequence/:projectId
تسلسل البنود
RBAC
Sequence
/planning/progress/:engineerId
تقارير المهندس
RBAC
Progress
📁 /users
/users
قائمة المستخدمين
ADMIN
List
/users/new
إنشاء مستخدم
ADMIN
Create
/users/:id
ملف المستخدم
ADMIN
Profile
/users/roles
إدارة الأدوار
ADMIN
Roles
/users/departments
الأقسام
ADMIN
Depts
📁 /operations
/operations/approvals
مركز الاعتمادات
RBAC
Approvals
/operations/inquiries
مركز الاستفسارات
RBAC
Inquiries
/operations/warehouse
المخزن
RBAC
Warehouse
/operations/purchasing
المشتريات
RBAC
Purchasing
/operations/accounting
الحسابات
RBAC
Accounting
📁 /vip ⭐ NEW
/vip/properties
إدارة العقارات
VIP
Properties
/vip/properties/:id
تفاصيل العقار
VIP
PropertyDetail
/vip/maintenance
جدول الصيانة
VIP
Maintenance
/vip/tenants
المستأجرين
VIP
Tenants
/vip/reports/quarterly
التقارير الربعية
VIP
Reports
📁 /reports
/reports
مركز التقارير
RBAC
Center
/reports/pnl
الأرباح والخسائر
RBAC
PnL
/reports/activity-log
سجل النشاط
ADMIN
ActivityLog
📁 /settings
/settings/system
إعدادات النظام
ADMIN
System
/settings/notifications
إعدادات الإشعارات
AUTH
Notifications
/settings/workflows
مصمم سير العمل
ADMIN
Workflows
/settings/profile
الملف الشخصي
AUTH
Profile
app.routes.ts (Sample)
import { Routes } from '@angular/router';
import { authGuard, roleGuard } from './core/guards';
export const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
// Public routes
{
path: 'auth',
loadChildren: () => import('./features/auth/auth.routes').then(m => m.AUTH_ROUTES)
},
// Protected routes
{
path: '',
component: DashboardLayoutComponent,
canActivate: [authGuard],
children: [
{ path: 'dashboard', loadComponent: () => import('./features/dashboard/overview.component') },
{ path: 'projects', loadChildren: () => import('./features/projects/projects.routes') },
{ path: 'planning', loadChildren: () => import('./features/planning/planning.routes') },
{ path: 'users', canActivate: [roleGuard(['admin'])], loadChildren: () => import('./features/users/users.routes') },
{ path: 'vip', canActivate: [roleGuard(['admin', 'vip-manager'])], loadChildren: () => import('./features/vip/vip.routes') }
]
},
{ path: '**', component: NotFoundComponent }
];
٢ · Route Guards

حراس المسارات

٤ guards لحماية المسارات والتحقق من الصلاحيات

lock
authGuard

يتحقق من وجود JWT صالح. يحوّل لـ /auth/login لو غير مصادق.

export const authGuard = () => {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isAuthenticated()) return true;
router.navigate(['/auth/login']);
return false;
};
admin_panel_settings
roleGuard

يتحقق من دور المستخدم (RBAC). يأخذ array من الأدوار المسموحة.

export const roleGuard = (roles: string[]) => {
return () => {
const user = inject(AuthService).currentUser;
if (roles.includes(user.role)) return true;
return createUrlTreeFromSnapshot('/403');
};
};
warning
unsavedChangesGuard

يحذّر المستخدم من فقدان البيانات قبل ترك صفحة بها form غير محفوظ.

export const unsavedGuard =
(component: { hasUnsaved: () => boolean }) => {
if (!component.hasUnsaved()) return true;
return confirm('يوجد تغييرات غير محفوظة. هل تريد المغادرة؟');
};
downloading
resourceResolver

يحمّل البيانات قبل دخول الصفحة (resolve guard).

export const projectResolver =
(route: ActivatedRouteSnapshot) => {
return inject(ProjectService)
.getById(route.params.id);
};
٣ · NgRx State Management

إدارة الحالة بـ NgRx

١٢ Store · Actions · Reducers · Effects · Selectors

شجرة الـ State العامة (Root)
interface AppState {
auth: AuthState; // المصادقة والمستخدم الحالي
ui: UiState; // loading · sidebar · theme · language
projects: ProjectsState; // قائمة المشاريع وفلاتر
planning: PlanningState; // جداول التخطيط والبنود ⭐
approvals: ApprovalsState;
inquiries: InquiriesState;
warehouse: WarehouseState;
purchasing: PurchasingState;
accounting: AccountingState;
vip: VipState; // عقارات VIP ⭐
notifications: NotificationsState;
reports: ReportsState;
}
ProjectsState (مثال)
interface ProjectsState {
list: Project[];
selected: Project | null;
filters: {
status?: ProjectStatus;
clientId?: string;
dateRange?: DateRange;
};
pagination: {
page: number;
pageSize: number;
total: number;
};
loading: boolean;
error: string | null;
}
Actions
export const ProjectActions = createActionGroup({
source: 'Projects',
events: {
'Load List': props<{ filters?: any }>(),
'Load Success': props<{ data: Project[] }>(),
'Load Failure': props<{ error: string }>(),
'Create': props<{ project: Project }>(),
'Update': props<{ id: string; changes: Partial<Project> }>(),
'Delete': props<{ id: string }>(),
'Select': props<{ id: string }>()
}
});
Reducer
export const projectsReducer = createReducer(
initialState,
on(ProjectActions.loadList, state =>
({ ...state, loading: true, error: null })),
on(ProjectActions.loadSuccess, (state, { data }) =>
({ ...state, list: data, loading: false })),
on(ProjectActions.loadFailure, (state, { error }) =>
({ ...state, loading: false, error }))
);
Effects
@Injectable()
export class ProjectsEffects {
loadList$ = createEffect(() =>
this.actions$.pipe(
ofType(ProjectActions.loadList),
switchMap(({ filters }) =>
this.api.getProjects(filters).pipe(
map(data => ProjectActions.loadSuccess({ data })),
catchError(err => of(ProjectActions.loadFailure({ error: err.message })))
)
)
)
);
}
Selectors (Memoized Queries)
export const selectProjectsState = createFeatureSelector<ProjectsState>('projects');
export const selectAllProjects = createSelector(selectProjectsState, s => s.list);
export const selectLoading = createSelector(selectProjectsState, s => s.loading);
export const selectActiveProjects = createSelector(
selectAllProjects,
projects => projects.filter(p => p.status === 'active')
);
// Usage in component:
projects$ = this.store.select(selectActiveProjects);
٤ · Folder Structure

هيكل المجلدات

Feature-based architecture · Scalable · Testable

📁 src/
├── 📁 app/
│ ├── 📁 core/ // Singleton services · Guards · Interceptors
│ │ ├── 📁 guards/
│ │ ├── 📁 interceptors/
│ │ ├── 📁 services/ // AuthService · ApiService · StorageService
│ │ └── 📁 models/
│ │
│ ├── 📁 shared/ // Reusable components · pipes · directives
│ │ ├── 📁 components/ // rk-button · rk-input · rk-table · ...
│ │ ├── 📁 pipes/
│ │ ├── 📁 directives/
│ │ └── 📁 utils/
│ │
│ ├── 📁 layouts/ // DashboardLayout · AuthLayout
│ │
│ ├── 📁 features/ // Lazy-loaded feature modules
│ │ ├── 📁 auth/
│ │ │ ├── 📁 components/
│ │ │ ├── 📁 pages/
│ │ │ ├── 📁 services/
│ │ │ ├── 📁 store/ // actions · reducer · effects · selectors
│ │ │ └── auth.routes.ts
│ │ ├── 📁 dashboard/
│ │ ├── 📁 projects/
│ │ ├── 📁 planning/ // ⭐ NEW
│ │ ├── 📁 users/
│ │ ├── 📁 operations/
│ │ │ ├── 📁 approvals/
│ │ │ ├── 📁 inquiries/
│ │ │ ├── 📁 warehouse/
│ │ │ ├── 📁 purchasing/
│ │ │ └── 📁 accounting/
│ │ ├── 📁 vip/ // ⭐ NEW
│ │ ├── 📁 reports/
│ │ └── 📁 settings/
│ │
│ ├── 📁 store/ // Root state · meta-reducers
│ │ ├── app.state.ts
│ │ └── index.ts
│ │
│ ├── app.component.ts
│ ├── app.config.ts
│ └── app.routes.ts
│
├── 📁 assets/ // Images · fonts · i18n
│ ├── 📁 i18n/
│ │ ├── ar.json
│ │ └── en.json
│ ├── 📁 images/
│ └── logo.png
│
├── 📁 environments/ // dev · staging · prod
│
├── 📁 styles/ // Global SCSS
│ ├── _variables.scss
│ ├── _mixins.scss
│ ├── _rtl.scss
│ └── styles.scss
│
└── index.html
Core
Singletons فقط · Guards · Interceptors · Auth · API · Storage
Shared
مكونات قابلة لإعادة الاستخدام في كل مكان · Stateless
Features
Modules مستقلة · Lazy loading · State خاص لكل feature
٥ · HTTP Interceptors

معترضات الـ HTTP

٥ interceptors لكل الطلبات

vpn_key
authInterceptor

يضيف JWT token لكل طلب · يحدّث الـ token عند انتهائه (refresh).

error
errorInterceptor

يلتقط كل الأخطاء · يعرض toast · يحوّل لـ /login عند 401 · /403 عند Forbidden.

downloading
loadingInterceptor

يفعّل loading indicator تلقائياً مع كل طلب.

cached
cacheInterceptor

يحفظ نتائج الـ GET requests للموارد الثابتة (countries · departments).

language
localeInterceptor

يضيف Accept-Language: ar أو en لكل طلب حسب اللغة المختارة.

٦ · Core Services

الخدمات الأساسية

٨ خدمات Singleton أساسية

AuthService
login · logout · refresh · currentUser · isAuthenticated · hasRole
ApiService
get · post · put · delete · upload · download (مع base URL)
StorageService
localStorage · sessionStorage · encrypted storage للـ tokens
ToastService
success · error · warn · info مع auto-dismiss
DialogService
confirm · alert · custom dialog · form dialog
NotificationService
SignalR connection · real-time updates · push handling
PermissionService
can(action) · canAny([actions]) · cached check
I18nService
setLang(ar|en) · translate(key) · RTL/LTR direction