مكتبات الواجهة والمعمارية — نظام إدارة المغسلة
معلومات الوثيقة
| الحقل |
القيمة |
| المشروع |
نظام إدارة المغسلة |
| الإصدار |
1.0 |
| اللغة |
العربية |
| الإطار |
Angular 19+ |
| نوع الوثيقة |
دليل مكتبات الواجهة للمطورين |
1. هيكل المشروع
frontend/laundry-app/
├── src/app/
│ ├── core/ # خدمات فردية، حراس، معترضات
│ │ ├── services/ # api-base، auth، print، export، license
│ │ ├── interceptors/ # jwt، client-token، error
│ │ └── guards/ # auth، license، role
│ ├── shared/ # مكونات وأنابيب وتوجيهات قابلة لإعادة الاستخدام
│ ├── modules/ # وحدات محملة بتحميل كسول
│ │ ├── dashboard/
│ │ ├── invoices/
│ │ ├── customers/
│ │ ├── payments/
│ │ ├── carpet/
│ │ ├── tailoring/
│ │ ├── inventory/
│ │ ├── reports/
│ │ ├── admin/
│ │ └── wizard/
│ └── layout/ # هيكل التطبيق، القائمة الجانبية، الرأس
├── assets/
│ ├── i18n/ {ar,en}.json
│ └── styles/ {_variables، _rtl، _print-thermal، _print-a4}.scss
├── src-tauri/ # Tauri (Rust)
└── {package، angular، tsconfig، jest، eslintrc، prettierrc}.json
2. قائمة حزم npm الكاملة
| الحزمة |
الغرض |
@angular/core، @angular/router، @angular/forms |
الإطار الأساسي |
@angular/service-worker |
PWA / تخزين مؤقت دون اتصال |
primeng |
مكتبة المكونات |
primeflex |
أدوات CSS |
primeicons |
الأيقونات |
chart.js |
الرسوم البيانية (عبر primeng/chart) |
@ngx-translate/core + @ngx-translate/http-loader |
ترجمة AR/EN |
rxjs |
برمجة تفاعلية |
xlsx (SheetJS) |
تصدير Excel |
html2canvas + jspdf |
PDF |
jsbarcode |
باركود |
@ngrx/store، @ngrx/effects، @ngrx/entity |
إدارة الحالة |
@ngrx/router-store |
مزامنة المتجر مع الموجه |
@ngrx/store-devtools |
أدوات تصحيح Redux |
@tauri-apps/api + @tauri-apps/cli |
جسر Tauri |
@tauri-apps/plugin-* (8 إضافات) |
shell، updater، dialog، fs، process، window-state، store، os |
jest + jest-preset-angular + @testing-library/angular |
اختبار |
eslint + @angular-eslint/builder |
تدقيق الكود |
prettier + prettier-plugin-organize-imports |
تنسيق الكود |
husky + lint-staged |
خطافات Git |
3. الأنماط المعمارية
نمط Smart/Dumb + Facade
الحاوية (Smart) العرض (Dumb)
┌──────────────────────┐ ┌──────────────────┐
│ تحقن Facade │──@Input──▶│ @Input() فقط │
│ async pipe │◀─@Output──│ @Output() فقط │
│ لا استدعاءات HTTP │ │ OnPush │
│ OnPush │ └──────────────────┘
└──────────────────────┘
│
Injectable Facade
┌─────────────────┐
│ لا تستورد NgRx │ ← المكونات لا تلمس Store مباشرة
│ dispatch + select│
└─────────────────┘
تدفق بيانات NgRx
مستخدم ← مكون ← Facade.dispatch(action) ← Action ← Effect ← API
↓
Success/Failure Action
↓
Reducer
↓
Selector ← حالة ← مكون (عرض)
4. NgRx — إدارة الحالة
تسجيل المتجر
provideStore({
invoices: invoiceReducer,
customers: customerReducer,
payments: paymentReducer,
carpet: carpetReducer,
tailoring: tailoringReducer,
inventory: inventoryReducer,
reports: reportReducer,
admin: adminReducer,
wizard: wizardReducer,
}),
provideEffects([InvoiceEffects, CustomerEffects, ...]),
provideStoreDevtools({ maxAge: 50 }),
الإجراءات (Actions)
export const InvoiceActions = createActionGroup({
source: 'Invoice',
events: {
'Load': emptyProps(),
'Load Success': props<{ invoices: InvoiceDto[] }>(),
'Load Failure': props<{ error: string }>(),
'Create': props<{ dto: CreateInvoiceDto }>(),
'Create Success': props<{ invoice: InvoiceDto }>(),
}
});
المخفض (Reducer)
export const invoiceReducer = createReducer(
initialState,
on(InvoiceActions.load, (s) => ({ ...s, loading: true })),
on(InvoiceActions.loadSuccess, (s, { invoices }) =>
invoiceAdapter.setAll(invoices, { ...s, loading: false })),
);
التأثيرات (Effects)
load$ = createEffect(() => this.actions$.pipe(
ofType(InvoiceActions.load),
switchMap(() => this.service.getAll().pipe(
map(invoices => InvoiceActions.loadSuccess({ invoices })),
catchError(error => of(InvoiceActions.loadFailure({ error })))
))
));
الواجهة (Facade)
@Injectable({ providedIn: 'root' })
export class InvoiceFacade {
store = inject(Store);
invoices$ = this.store.select(selectAllInvoices);
load() { this.store.dispatch(InvoiceActions.load()); }
create(dto: CreateInvoiceDto) { this.store.dispatch(InvoiceActions.create({ dto })); }
}
5. PrimeNG
providePrimeNG({
theme: { preset: Aura },
ripple: true,
});
6. الترجمة (ngx-translate)
provideTranslateService({
defaultLanguage: 'ar',
useDefaultLang: true,
});
7. تكامل Tauri
@Injectable({ providedIn: 'root' })
export class TauriBridgeService {
isTauri = !!(window as any).__TAURI_INTERNALS__;
async startDockerServices() {
const { invoke } = await import('@tauri-apps/api/core');
return invoke('start_docker_services');
}
async computeClientToken() {
const { invoke } = await import('@tauri-apps/api/core');
return invoke('compute_client_token');
}
}
8. خدمات الطباعة
printThermalReceipt(element: HTMLElement) {
const w = window.open('', '_blank', 'width=300');
w!.document.write(`<html><head><link rel="stylesheet" href="styles/_print-thermal.scss"></head>
<body>${element.innerHTML}</body></html>`);
w!.print(); w!.close();
}
9. خدمات التصدير
toExcel(data: any[], filename: string) {
const ws = XLSX.utils.json_to_sheet(data);
XLSX.writeFile(XLSX.utils.book_new(ws), `${filename}.xlsx`);
}
async toPDF(element: HTMLElement, filename: string) {
const canvas = await html2canvas(element, { scale: 2 });
const pdf = new jsPDF('p', 'mm', 'a4');
pdf.addImage(canvas.toDataURL(), 'PNG', 0, 0, 210, h);
pdf.save(`${filename}.pdf`);
}
10. هيكل المسارات
export const routes: Routes = [
{ path: 'login', loadComponent: () => import('./login/login.component') },
{ path: 'wizard', loadChildren: () => import('./modules/wizard/routes') },
{ path: '',
canActivate: [AuthGuard],
loadComponent: () => import('./layout/app-shell/app-shell.component'),
children: [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', loadChildren: () => import('./modules/dashboard/routes') },
{ path: 'invoices', loadChildren: () => import('./modules/invoices/routes') },
{ path: 'customers', loadChildren: () => import('./modules/customers/routes') },
{ path: 'payments', loadChildren: () => import('./modules/payments/routes') },
{ path: 'carpet', loadChildren: () => import('./modules/carpet/routes') },
{ path: 'tailoring', loadChildren: () => import('./modules/tailoring/routes') },
{ path: 'inventory', loadChildren: () => import('./modules/inventory/routes') },
{ path: 'reports', loadChildren: () => import('./modules/reports/routes') },
{ path: 'admin', loadChildren: () => import('./modules/admin/routes'), canActivate: [RoleGuard] },
]
},
];
11. معترضات HTTP
// jwt: يحقن Authorization: Bearer
// client-token: يحقن X-Laundry-Client-Token (للفروع غير المتصلة فقط)
// error: يعالج أخطاء 4xx/5xx عالمياً
// loading: مؤشر تحميل عالمي
provideHttpClient(withInterceptors([jwt, clientToken, error, loading]))
12. اتفاقيات الكود
| الاتفاقية |
القاعدة |
| الملفات |
kebab-case للملفات. PascalCase للصنف. |
| المكونات |
الحاويات الذكية تلحق بـ -container. البكماء باسم وصفي. |
| الخدمات |
Service لـ API. Facade للتجريد عن المتجر. |
| النماذج |
واجهات TypeScript فقط. |
| التغيير |
OnPush على جميع المكونات. |
| مستقل |
جميع المكونات standalone: true. |
| الترجمة |
لا تكتب نصوصاً عربية أو إنجليزية مباشرة. استخدم translate. |
13. ESLint + Prettier
// .prettierrc
{ "singleQuote": true, "trailingComma": "all", "printWidth": 100, "tabWidth": 2 }
سجل المراجعة
| التاريخ |
الإصدار |
المعد |
التغييرات |
| 2026-05-10 |
1.0 |
قائد الواجهة |
الإصدار الأولي لدليل مكتبات الواجهة |