Commit 3f48d457 authored by hasan khaddour's avatar hasan khaddour

fix s

parent c7831f2c
......@@ -57,6 +57,10 @@ export const routes: Routes = [
loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule)
}
, {
path: 'tracks',
loadChildren: () => import('./tracks/tracks.module').then(m => m.TracksModule)
}
]
}
......
import { Component } from '@angular/core';
@Component({
selector: 'add-customer-modal',
templateUrl: './add-customer-modal.component.html',
styleUrl: './add-customer-modal.component.css'
})
export class AddCustomerModalComponent {
}
......@@ -9,6 +9,7 @@ import { CustomerRoutingModule } from './customer-routing.module';
import { SharedModule } from "../shared/shared.module";
import { CustomerItemComponent } from './components/customer-item/customer-item.component';
import { CustomerCreateComponent } from './pages/customer-create/customer-create.component';
import { AddCustomerModalComponent } from './components/add-customer-modal/add-customer-modal.component';
......@@ -18,7 +19,8 @@ import { CustomerCreateComponent } from './pages/customer-create/customer-create
CustomerDetailsComponent,
UpdateCustomerComponent,
CustomerItemComponent,
CustomerCreateComponent
CustomerCreateComponent,
AddCustomerModalComponent
],
imports: [
CommonModule,
......
......@@ -47,26 +47,29 @@
<div class="row">
<div class="mb-3 col-5 offset-1">
<label for="stepName" class="form-label">نوع الكلفة</label>
<label for="stepName" class="form-label">الجهة الطارحة</label>
<input type="text" name="stepName" id="stepName" class="form-control" [(ngModel)]="selectedCustomer.customerName" required>
</div>
<div class="mb-3 col-5">
<label for="expectedSpendingDate" class="form-label">تاريخ الانفاق المتوقع</label>
<label for="expectedSpendingDate" class="form-label">البريد الاكتروني</label>
<input type="date" id="expectedSpendingDate" class="form-control" [(ngModel)]="selectedCustomer.email" name="expectedSpendingDate" required>
</div>
<hr>
العنوان
<div class="mb-3 col-4 offset-1">
<label for="local" class="form-label">الشراء المحلي</label>
<label for="local" class="form-label">المدينة</label>
<input id="local" class="form-control" [(ngModel)]="selectedCustomer.address.city" name="local" required>
</div>
<div class="mb-3 col-4 ">
<label for="completion" class="form-label">الشراء الخارجي </label>
<label for="completion" class="form-label">اسم الشارع </label>
<input id="completion" class="form-control" [(ngModel)]="selectedCustomer.address.streetName" name="completion" required>
</div>
<div class="mb-3 col-2">
<label for="duration" class="form-label">نوغ القطع</label>
<label for="duration" class="form-label">رقم الشارع</label>
<input type="number" id="duration" class="form-control select " [(ngModel)]="selectedCustomer.address.streetNumber" name="duration" required>
</div>
</div>
......
......@@ -86,7 +86,7 @@
<!-- Delete Confirmation -->
<div *ngIf="modalMode === 'delete'">
<p>هل أنت متأكد من أنك تريد حذف عنصر {{ selectedItem.costType }}?</p>
<button type="button" class="btn m-4 btn-danger" (click)="deleteProject()">Delete</button>
<button type="button" class="btn m-4 btn-danger" (click)="delete()">Delete</button>
<button type="button" class="btn m-4 btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</div>
......
......@@ -70,6 +70,7 @@ export class FinancialSpendingComponent {
})
}
openModal(mode: 'edit' | 'delete', item: FinancialSpending): void {
this.modalMode = mode;
this.selectedItem = { ...item }; // Clone project to prevent direct mutation
......@@ -110,7 +111,7 @@ export class FinancialSpendingComponent {
}
deleteProject(): void {
delete(): void {
let request : RemoveFinancialSpendItemRequest= {
projectId: this.projectId ,
id: this.selectedItem.id
......
......@@ -77,6 +77,30 @@
</div> <!-- .row -->
</div>
<hr>
<hr>
<div class="row align-items-center mb-4">
<div class="col-auto ">
<strong>متابعة المشروع</strong>
</div>
<div class="row">
<div class="col-md-6 col-lg-4" (click)="this.router.navigate(['/tracks/project/',project.id])">
<div class="card shadow mb-4">
<div class="card-body file-list">
<div class="d-flex align-items-center">
<div class="circle circle-md bg-secondary">
<span class="fe fe-credit-card fe-16 text-white"></span>
</div>
<div class="flex-fill ml-4 fname">
<strong>المتابعة</strong><br />
</div>
</div>
</div> <!-- .card-body -->
</div> <!-- .card -->
</div>
</div>
<hr>
<div class="row align-items-center mb-4">
......@@ -146,7 +170,24 @@
</div>
</div> <!-- /.row -->
</div> <!-- /.card-body -->
</div> <!-- /.card -->
<div class="row mt-5">
<div class="col-2 text-center">
<img src="/assets/images/users/4.jpg" class="navbar-brand-img brand-sm mx-auto my-4" alt="...">
</div>
<div class="col-8">
</div>
<div class="col-2 text-center">
<img src="/assets/images/users/4.jpg" class="navbar-brand-img brand-sm mx-auto my-4" alt="...">
</div>
</div> <!-- /.row -->
</div> <!-- /.card-body -->
</div> <!-- /.card -->
</div> <!-- /.col-12 -->
</div>
</div> <!-- .container-fluid -->
......@@ -55,11 +55,12 @@ export class StepListComponent {
if (result) {
// Add the new project to the list
this.steps.push(result);
console.log('Project added:', result);
}
}, (reason) => {
// Handle modal dismiss
console.log('Modal dismissed with reason:', reason);
this.toastr.error("لقد حدث خطاء ما")
});
}
}
......@@ -106,11 +106,6 @@
<i class="bi bi-circle"></i><span>المشاريع التي أرأسها</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link collapsed">
<i class="bi bi-circle"></i><span>تخطيط مشروع</span>
</a>
</li>
<li class="nav-heading">العمل</li>
......
<p>employee-track works!</p>
<div class="card shadow mb-4 col-9 offset-1">
<div class="card-header ">
<div class="row align-items-center">
<div class="col ml-n2">
<strong class="mb-1"> انشغالية العامل {{employeeTrack.employee.personalInfo | fullname}}</strong><span class=" ml-1"></span>
<p class="small text-muted mb-1">الملاحظات {{employeeTrack.notes}}</p>
</div>
</div>
</div>
<div class="card-body ">
<div class="row align-items-center">
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted flex-fill">ساعات العمل المسندة {{employeeTrack.employeeWork.assignedWorkingHours}}</span>
<span class="text-muted ">ساعات العمل الفعلية {{employeeTrack.employeeWork.workedHours}}</span>
<span class="text-muted">نسبة المساهمة في العمل {{employeeTrack.employeeWork.contributingRatio}}</span>
</div>
</div>
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted flex-fill">العمل المسند {{employeeTrack.employeeWorkInfo.assignedWork}}</span>
<span class="text-muted ">تاريخ انتهائه من العمل المسند {{employeeTrack.employeeWorkInfo.assignedWorkEnd | date}}</span>
<span class="text-muted">العمل المنفذ {{employeeTrack.employeeWorkInfo.performedWork}}</span>
</div>
</div>
<div class="col-8 ">
<div class="col-auto">
<button type="button" class="btn m-2 btn-sm btn-secondary">المساهمات</button>
<button type="button" class="btn m-2 btn-sm btn-secondary">تعديل</button>
</div>
</div>
</div>
</div> <!-- / .card-body -->
</div>
\ No newline at end of file
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';
import { EmployeeTrack } from '../../models/responses/employeeTrack';
@Component({
selector: 'employee-track',
......@@ -7,4 +8,5 @@ import { Component } from '@angular/core';
})
export class EmployeeTrackComponent {
@Input() employeeTrack :EmployeeTrack
}
import { Component } from '@angular/core';
@Component({
selector: 'add-employee-track-modal',
templateUrl: './add-employee-track-modal.component.html',
styleUrl: './add-employee-track-modal.component.css'
})
export class AddEmployeeTrackModalComponent {
}
.modal-backdrop {
background-color: transparent !important; /* يجعل الخلفية شفافة تمامًا */
}
<div class="modal fade" id="addStepTrackModal" tabindex="-1" aria-labelledby="addStepTrackModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addStepTrackModalLabel">Add Step Track</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form [formGroup]="stepTrackForm" (ngSubmit)="onSubmit()">
<div class="mb-3">
<label for="stepName" class="form-label">Step Name</label>
<input type="text" id="stepName" formControlName="stepName" class="form-control" [ngbTypeahead]="search" (selectItem)="onStepSelected($event.item)">
</div>
<div class="mb-3">
<label for="executionState" class="form-label">Execution State</label>
<input type="text" id="executionState" formControlName="executionState" class="form-control">
</div>
<div class="mb-3">
<label for="trackExecutionRatio" class="form-label">Track Execution Ratio</label>
<input type="number" id="trackExecutionRatio" formControlName="trackExecutionRatio" class="form-control" min="0" max="100">
</div>
<button type="submit" class="btn btn-primary" [disabled]="!stepTrackForm.valid">Add Step Track</button>
</form>
</div>
</div>
</div>
</div>
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Track } from '../../../models/responses/track';
import { CreateTrackRequest } from '../../../models/requests/CreateTrackRequest';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { FinancialSpendingService } from '../../../../projects/services/financial-spending.service';
import { TrackService } from '../../../services/track.service';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Observable, startWith, map } from 'rxjs';
import { Step } from '../../../../projects/models/responses/Step';
import { AddStepTrackRequest } from '../../../models/requests/AddStepTrackRequest';
import { Modal } from 'bootstrap';
import { StepService } from '../../../../projects/services/step.service';
@Component({
selector: 'add-step-track-modal',
templateUrl: './add-step-track-modal.component.html',
styleUrl: './add-step-track-modal.component.css'
})
export class AddStepTrackModalComponent {
@Input() isVisible = false;
@Input() steps: Step[] = []; // All steps available for the project
@Input() trackedSteps: Step[] = []; // Steps that are already tracked
@Input() trackId :number
@Output() addStepTrack = new EventEmitter<AddStepTrackRequest>();
stepTrackForm: FormGroup;
filteredSteps: Step[] = [];
constructor(private fb: FormBuilder,
private stepService : StepService
) {
this.stepTrackForm = this.fb.group({
stepName: ['', Validators.required],
executionState: ['', Validators.required],
trackExecutionRatio: [0, [Validators.required, Validators.min(0), Validators.max(100)]],
});
}
ngOnInit(): void {
this.filteredSteps = this.steps.filter(step =>
!this.trackedSteps.some(trackedStep => trackedStep.id === step.id)
);
}
search = (text$: Observable<string>) =>
text$.pipe(
map(term => term.length < 2 ? [] :
this.filteredSteps.filter(v => v.stepInfo.stepName.toLowerCase().includes(term.toLowerCase())).slice(0, 10))
);
onStepSelected(step: Step): void {
this.stepTrackForm.patchValue({ stepName: step.stepInfo.stepName });
}
onSubmit(): void {
if (this.stepTrackForm.valid) {
const selectedStep = this.filteredSteps.find(step => step.stepInfo.stepName === this.stepTrackForm.value.stepName);
if (selectedStep) {
const newStepTrack: AddStepTrackRequest = {
stepId: selectedStep.id,
trackId: this.trackId,
executionState: this.stepTrackForm.value.executionState,
trackDate: new Date(),
trackExecutionRatio: this.stepTrackForm.value.trackExecutionRatio,
};
this.addStepTrack.emit(newStepTrack);
this.closeModal();
}
}
}
closeModal(): void {
const modal = document.getElementById('addStepTrackModal');
if (modal) {
const bootstrapModal = new Modal(modal);
bootstrapModal.hide();
}
}
}
<div class="modal-header">
<button type="button" class="btn-close" (click)="onClose()" ></button>
<h5 class="modal-title text-center">إضافة عملية متابعة </h5>
</div>
<div class="modal-body">
<form (ngSubmit)="onSubmit()" #projectForm="ngForm">
<div class="row">
<div class="mb-3 col-8 offset-1">
<label for="completion" class="form-label">الوضع الراهن </label>
<input id="completion" class="form-control" [(ngModel)]="request.trackInfo.statusDescription" name="completion" required>
</div>
<div class="mb-3 col-8 offset-1">
<label for="duration" class="form-label">الملاحظات</label>
<input id="duration" class="form-control select " [(ngModel)]="request.notes" name="duration" required>
</div>
</div>
<div class="row ">
<button type="submit" class=" col-3 btn btn-primary">إضافة</button>
<button class="btn btn-seondary col-3" (click)="onClose()" >إغلاق</button>
</div>
</form>
</div>
\ No newline at end of file
import { Component, Input } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { CreateTrackRequest } from '../../../models/requests/CreateTrackRequest';
import { Track } from '../../../models/responses/track';
import { TrackService } from '../../../services/track.service';
@Component({
selector: 'add-track-modal',
templateUrl: './add-track-modal.component.html',
styleUrl: './add-track-modal.component.css'
})
export class AddTrackModalComponent {
item = new Track()
@Input() projectId : number
request :CreateTrackRequest
constructor(private toastr :ToastrService, public activeModal: NgbActiveModal,private trackService : TrackService) {}
ngOnInit(): void {
this.request ={
projectId: this.projectId ,
trackInfo: {
trackDate: new Date(),
statusDescription: "",
isCompleted :false
},
notes:""
};
}
onSubmit(): void {
// Emit the project data or handle it as needed
console.log('Project data submitted:', this.request);
this.trackService.createTrack(this.request).subscribe({
next: (data)=>{
this.activeModal.close(data); // Close modal and pass data
},
error: (err )=> this.toastr.error("لقد حدث خطاء ما")
})
}
onClose():void {
this.activeModal.close();
}
}
<p>step-track works!</p>
<div class="card shadow mb-4 col-9 offset-1">
<div class="card-header ">
<div class="row align-items-center">
<div class="col ml-n2">
<strong class="mb-1"> متابعة مرحلة {{stepTrack.stepInfo.stepName}}</strong><span class=" ml-1"></span>
<p class="small text-muted mb-1">وضع التنفيذ {{stepTrack.executionState}}</p>
</div>
</div>
</div>
<div class="card-body ">
<div class="row align-items-center">
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted flex-fill">نسبة التنفيذ الحالية {{stepTrack.trackExecutionRatio + stepTrack.oldExecutionRatio}}</span>
<span class="text-muted">نسبة التنفيذ قبل {{stepTrack.oldExecutionRatio}}</span>
</div>
</div>
<div class="col-8 ">
<div class="col-auto">
<button type="button " class="btn m-2 btn-sm btn-secondary">تاريخ المتابعة</button>
<button type="button" class="btn m-2 btn-sm btn-secondary">تعديل</button>
</div>
</div>
</div>
</div> <!-- / .card-body -->
</div>
\ No newline at end of file
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';
import { StepTrack } from '../../models/responses/steptrack';
@Component({
selector: 'step-track',
......@@ -7,4 +8,5 @@ import { Component } from '@angular/core';
})
export class StepTrackComponent {
@Input() stepTrack :StepTrack
}
<div class="card shadow mb-4 col-8 offset-2">
<div class="card-header py-3">
<div class="row align-items-center">
<div class="col-auto">
<a href="profile-posts.html" class="avatar avatar-md">
<img src="./assets/images/users/4.jpg" alt="..." class="avatar-img rounded-circle">
</a>
</div>
<div class="col ml-n2">
<strong class="mb-1">متابعة {{track.projectInfo.name}}</strong><span class=" ml-1"></span>
<p class="small text-muted mb-1">الوضع الراهن {{track.trackInfo.statusDescription}}</p>
</div>
<div class="col-auto">
</div>
</div>
</div>
<div class="card-body ">
<div class="row align-items-center">
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted flex-fill">الملاحظات {{track.notes}}</span>
<span class="text-muted">تاريخ المتابعة {{track.trackInfo.trackDate| date}}</span>
</div>
</div>
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted badge flex-fill">{{track.trackInfo.isCompleted ? 'مكتملة':'غير مكتملة'}} </span>
</div>
<div class="col-auto">
<button type="button" [routerLink]="['/tracks/detail/',track.id]" class="btn m-2 btn-sm btn-secondary">تفاصيل المتابعة</button>
<button type="button" (click)="onDelete()"class="btn m-2 btn-sm btn-danger">إزالة</button>
</div>
</div>
</div>
</div> <!-- / .card-body -->
</div>
\ No newline at end of file
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Track } from '../../models/responses/track';
@Component({
selector: 'track-item',
templateUrl: './track-item.component.html',
styleUrl: './track-item.component.css'
})
export class TrackItemComponent {
@Input() track :Track
@Output() edit = new EventEmitter<void>();
@Output() delete = new EventEmitter<void>();
onDelete() {
this.delete.emit();
}
}
export class UpdateStepTrack {
stepTrackId: number;
trackId: numebr;
trackId: number;
stepId: number;
executionState: String;
trackDate: Date;
......
import { Employee } from "../../../employees/models/responses/employee"
import { EmployeeWork } from "../valueObjects/EmployeeWork"
import { EmployeeWorkInfo } from "../valueObjects/EmployeeWorkInfo"
import { TrackInfo } from "../valueObjects/trackInfo"
......@@ -5,7 +6,8 @@ import { TrackInfo } from "../valueObjects/trackInfo"
export class EmployeeTrack {
emloyeeId :number
trackId :number
rrackInfo :TrackInfo
employee : Employee
trackInfo :TrackInfo
employeeWorkInfo : EmployeeWorkInfo
employeeWork :EmployeeWork
notes :string
......
......@@ -7,7 +7,7 @@ export class StepTrack {
trackId :number
stepInfo :StepInfo
trackInfo :TrackInfo
executionState :number
executionState :string
trackExecutionRatio :number
oldExecutionRatio : number
......
import { ProjectInfo } from "../../../projects/models/valueObjects/ProjectInfo"
import { TrackInfo } from "../valueObjects/trackInfo"
export class Track {
......@@ -5,4 +6,5 @@ export class Track {
trackInfo :TrackInfo
notes : string
projectId :number
}
\ No newline at end of file
projectInfo : ProjectInfo
}
import { Component } from '@angular/core';
@Component({
selector: 'trac-create',
templateUrl: './trac-create.component.html',
styleUrl: './trac-create.component.css'
})
export class TracCreateComponent {
}
import { Component } from '@angular/core';
@Component({
selector: 'track-create',
templateUrl: './track-create.component.html',
styleUrl: './track-create.component.css'
})
export class TrackCreateComponent {
projectId : Number
constructor(){}
}
<p>track-details works!</p>
<section *ngIf="stepTracks && track && employeesTracks&&trackedSteps&&steps" class="section profile">
<div class="row">
<div class="col-xl-4">
<div class="card">
<div class="card-body profile-card pt-4 d-flex flex-column align-items-center">
<img src="assets/images/users/4.jpg" alt="Profile" class="">
<h2>{{track.projectInfo.name}}</h2>
<h3>رمز المشروع : {{track.projectInfo.code}}</h3>
<div class="social-links mt-2">
</div>
</div>
</div>
</div>
<div class="col-xl-8">
<div class="card">
<div class="card-body pt-3">
<!-- Bordered Tabs -->
<ul class="nav nav-tabs nav-tabs-bordered" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link pr-2 pl-2 text-center active" data-bs-toggle="tab" data-bs-target="#profile-overview" aria-selected="true" role="tab" tabindex="-1">ملخص </button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link pr-1 pl-1 " data-bs-toggle="tab" data-bs-target="#profile-edit" aria-selected="false" role="tab">متابعة المراحل</button>
</li>
<li class="nav-item pr-1 pl-1" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#profile-settings" aria-selected="false" tabindex="-1" role="tab">متابعة الموظفين</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link pr-1 pl-1" data-bs-toggle="tab" data-bs-target="#profile-change-password" aria-selected="false" tabindex="-1" role="tab">التقارير المرتبطة</button>
</li>
</ul>
<div class="tab-content pt-2">
<div class="tab-pane fade profile-overview active show" id="profile-overview" role="tabpanel">
<h5 class="card-title">وصف المشروع </h5>
<p class="small fst-italic">{{track.projectInfo.description}}</p>
<div class="row">
<div class="col-8 label ">الوضع الراهن {{track.trackInfo.statusDescription}}</div>
</div>
<div class="row">
<div class="col-8 label ">الملاحظات {{track.notes}}</div>
</div>
<div class="row">
<div class="col-6 label ">تاريخ عملية المتابعة {{track.trackInfo.trackDate | date}}</div>
<button class="col-2 mr-1 btn btn-primary" *ngIf="!track.trackInfo.isCompleted">اكمال المتابعة</button>
<div class="col-2 btn disabled btn-success ">{{track.trackInfo.isCompleted ? 'مكتملة':'غير مكتملة'}}</div>
</div>
</div>
<div class="tab-pane fade profile-edit pt-3 " id="profile-edit" role="tabpanel">
<button class="btn btn-primary" (click)="showAddStepTrackModal()">متابعة مرحلة</button>
<hr>
<step-track *ngFor="let stepTrack of stepTracks" [stepTrack]="stepTrack" ></step-track>
<div class="row" *ngIf="stepTracks.length ==0 " >
لم تقم بمتابعة اية مراحل
</div>
</div>
<div class="tab-pane fade pt-3" id="profile-settings" role="tabpanel">
<employee-track *ngFor="let employeeTrack of employeesTracks" [employeeTrack]="employeeTrack" ></employee-track>
<div class="row" *ngIf="employeesTracks.length ==0 " >
لم تقم بمتابعة اي مشارك
</div>
</div>
<div class="tab-pane fade pt-3" id="profile-change-password" role="tabpanel">
<div class="row" >
<button class="btn btn-primary col-3 offset-1">تقرير انشغالية عاملين </button>
<button class="btn btn-primary col-3 offset-1">تقرير متابعة مراحل </button>
</div>
</div>
</div><!-- End Bordered Tabs -->
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addStepTrackModal">
Add Step Track
</button>
<add-step-track-modal
[steps]="steps"
[trackedSteps]="trackedSteps"
(addStepTrack)="handleAddStepTrack($event)">
</add-step-track-modal>
</section>
\ No newline at end of file
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { TrackService } from '../../services/track.service';
import { Track } from '../../models/responses/track';
import { StepTrack } from '../../models/responses/steptrack';
import { EmployeeTrack } from '../../models/responses/employeeTrack';
import { ActivatedRoute } from '@angular/router';
import { Step } from '../../../projects/models/responses/Step';
import { AddStepTrackRequest } from '../../models/requests/AddStepTrackRequest';
import { error } from 'jquery';
import { StepService } from '../../../projects/services/step.service';
import { forkJoin } from 'rxjs';
@Component({
selector: 'track-details',
templateUrl: './track-details.component.html',
styleUrl: './track-details.component.css'
})
export class TrackDetailsComponent {
export class TrackDetailsComponent implements OnInit {
isAddStepTrackModalVisible = false;
trackId : number
track : Track
stepTracks :StepTrack[]
employeesTracks : EmployeeTrack[]
steps: Step[] = []; // Load steps from service or store
trackedSteps: Step[] = []; // Load already tracked steps
constructor(
private toastr : ToastrService ,
private route :ActivatedRoute,
private trackService : TrackService,
private stepService : StepService
){}
ngOnInit(): void {
this.trackId=Number(this.route.snapshot.paramMap.get('id'));
this.loadTrack();
}
loadTrack(){
forkJoin({
track: this.trackService.getByTrackById(this.trackId),
stepTracks: this.trackService.getStepsTrackById(this.trackId),
employeesTracks: this.trackService.getEmployeesTrackById(this.trackId)
}).subscribe(({ track, stepTracks, employeesTracks }) => {
this.track = track;
this.stepTracks = stepTracks;
this.employeesTracks = employeesTracks;
this.loadSteps();
})
}
loadSteps(){
this.stepService
.getStepsByProject(this.track.projectId)
.subscribe({
next: (data)=> {
this.steps=data ;
this.filterTrackedSteps();
this.filterUntrackedSteps()
}
});
}
filterTrackedSteps(): void {
this.trackedSteps = this.steps.filter(step =>
this.stepTracks.some(track => track.stepId === step.id)
);
}
filterUntrackedSteps(): void {
this.steps = this.steps.filter(step =>
!this.stepTracks.some(track => track.stepId === step.id)
);
}
showAddStepTrackModal(): void {
this.isAddStepTrackModalVisible = true;
}
closeAddStepTrackModal(): void {
this.isAddStepTrackModalVisible = false;
}
handleAddStepTrack(stepTrackRequest: AddStepTrackRequest): void {
stepTrackRequest.trackDate=this.track.trackInfo.trackDate
this.trackService.addStepTrack(stepTrackRequest).subscribe({
next : (data)=>{
this.loadTheNewStep(data,stepTrackRequest);
}
,
error:(err)=>{
this.toastr.error('لقد حدث خطاء ما')
}
});
}
loadTheNewStep(stId :number,request :AddStepTrackRequest ){
let s = this.steps.find(s => s.id == request.stepId )
let st : StepTrack ={
id:stId ,
trackId:this.trackId,
trackInfo:this.track.trackInfo,
trackExecutionRatio:request.trackExecutionRatio ,
executionState: request.executionState,
oldExecutionRatio : s?.currentCompletionRatio ??0 ,
stepInfo:s?.stepInfo ?? {
startDate:new Date(),
stepName :'',
NumberOfWorker:0,
description:'',
duration:0
},
stepId: s?.id??0
}
this.stepTracks.push(st)
this.steps=this.steps.filter(e => e.id == s?.id)
this.trackedSteps.push(s!);
}
}
<p>tracks works!</p>
<section *ngIf="tracks" class="row">
<div class="row justify-content-center">
<div class="col-12">
<div class="row align-items-center my-4">
<div class="col">
<h2 class="h3 mb-0 page-title"> قائمة عمليات المتابعة </h2>
</div>
<div class="col-auto">
<button type="button" (click)="openAddModal()" class="btn btn-primary"><span class="fe fe-file-plus fe-12 mr-2"></span>إضافة متابعة </button>
</div>
</div>
<hr>
<track-item class=" offset-2"
*ngFor="let track of tracks"
[track]="track"
(delete)="openModal('delete', track)"
></track-item>
<div *ngIf="tracks.length==0">
للأسف هذا المروع لايحوي على أية مراحل
</div>
</div>
</div>
</section>
<div class="modal fade" id="trackModal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<h5 class="modal-title" id="modalLabel">{{ modalTitle }}</h5>
</div>
<div class="modal-body">
<!-- Delete Confirmation -->
<div *ngIf="modalMode === 'delete'">
<p>هل أنت متأكد من أنك تريد حذف متابعة {{ selectedItem.projectInfo.name }} التي حدثت بتاريخ {{selectedItem.trackInfo.trackDate | date}}?</p>
<button type="button" class="btn m-4 btn-danger" (click)="deleteTrack()">Delete</button>
<button type="button" class="btn m-4 btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { TrackService } from '../../services/track.service';
import { Track } from '../../models/responses/track';
import { ToastrService } from 'ngx-toastr';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { AddTrackModalComponent } from '../../components/modals/add-track-modal/add-track-modal.component';
import { GetTracksByProjectRequest } from '../../models/requests/GetTracksByProjectRequest';
import { Modal } from 'bootstrap';
import { RemoveTrackRequest } from '../../models/requests/RemoveTrackRequest';
@Component({
selector: 'tracks',
templateUrl: './tracks.component.html',
styleUrl: './tracks.component.css'
})
export class TracksComponent {
export class TracksComponent implements OnInit{
projectId : number
tracks : Track[]
selectedItem : Track
modalMode: 'edit' | 'delete' = 'edit';
modalTitle: string = '';
constructor(
private route :ActivatedRoute ,
private router :Router,
private trackService : TrackService,
private toastr : ToastrService,
private modalService : NgbModal
){
}
ngOnInit(): void {
this.projectId=Number(this.route.snapshot.paramMap.get('id'));
this.loadTracks();
}
loadTracks(){
let request : GetTracksByProjectRequest = {
projectId: this.projectId ,
pageNumber:null,
pageSize:null
}
this.trackService
.getTrackByProjectId(request)
.subscribe({
next : (data)=>{
this.toastr.success("تم تحميل عمليات المتابعة بنجاح");
this.tracks= data;
}
,
error:(err)=>{
this.toastr.error("لقد حدث خطاء ما")
}
});
}
openAddModal(): void {
const modalRef = this.modalService.open(AddTrackModalComponent);
modalRef.componentInstance.projectId = this.projectId;
modalRef.result.then((result) => {
if (result) {
this.tracks.push(result);
this.toastr.success("تمت الإضافة بنجاح")
}
}, (reason) => {
});
}
openModal(mode: 'edit' | 'delete', item: Track): void {
this.modalMode = mode;
this.selectedItem = { ...item }; // Clone project to prevent direct mutation
console.log(this.selectedItem)
if (mode === 'edit') {
this.modalTitle = 'تعديل عنصر ';
} else if (mode === 'delete') {
this.modalTitle = 'حذف عنصر';
}
const modalElement = document.getElementById('trackModal');
if (modalElement) {
new Modal(modalElement).show(); // Open the modal
}
}
deleteTrack(): void {
let request : RemoveTrackRequest= {
trackId: this.projectId ,
}
this.trackService.removeTrack(request).subscribe({
next :()=>{
this.tracks = this.tracks.filter(p => p.id !== this.selectedItem.id);
this.toastr.success("تم الحذف بنجاح")
this.closeModal();
}
,
error:(err)=>{
this.toastr.error("لقد حدث خطاء ما ")
this.closeModal();
}
}
);
}
closeModal(): void {
const modalElement = document.getElementById('trackModal');
if (modalElement) {
new Modal(modalElement).hide(); // Close the modal
}
}
}
......@@ -12,6 +12,7 @@ import { CreateTrackRequest } from '../models/requests/CreateTrackRequest';
import { GetTracksByProjectRequest } from '../models/requests/GetTracksByProjectRequest';
import { RemoveTrackRequest } from '../models/requests/RemoveTrackRequest';
import { UpdateEmployeeWorkTrackRequest } from '../models/requests/UpdateEmployeeWorkTrackRequest';
import { EmployeeTrack } from '../models/responses/employeeTrack';
@Injectable({
providedIn: 'root'
......@@ -26,9 +27,7 @@ export class TrackService {
return this
.http
.get<Track>(`
${this.config.getServerUrl()}
/Tracks/${trackId}}`
.get<Track>(`${this.config.getServerUrl()}/Tracks/${trackId}`
);
}
......@@ -38,20 +37,16 @@ export class TrackService {
return this
.http
.get<StepTrack[]>(`
${this.config.getServerUrl()}
/Tracks/GetStepsTrack/${trackId}}`
.get<StepTrack[]>(`${this.config.getServerUrl()}/Tracks/GetStepsTrack/${trackId}`
);
}
// this method retreive the employees track by track id
//
public getEmployeesTrackById(trackId : number ):Observable<StepTrack[]>{
public getEmployeesTrackById(trackId : number ):Observable<EmployeeTrack[]>{
return this
.http
.get<StepTrack[]>(`
${this.config.getServerUrl()}
/Tracks/GetEmployeesTrack/${trackId}}`
.get<EmployeeTrack[]>(`${this.config.getServerUrl()}/Tracks/GetEmployeesTrack/${trackId}`
);
}
......@@ -63,9 +58,7 @@ export class TrackService {
return this
.http
.get<Track[]>(`
${this.config.getServerUrl()}
/Tracks/GetTracksByProject/?projectId=${request.projectId}${pagination}}`
.get<Track[]>(`${this.config.getServerUrl()}/Tracks/GetTracksByProject/?projectId=${request.projectId}${pagination}`
);
}
......@@ -75,9 +68,7 @@ export class TrackService {
return this
.http
.post<number>(`
${this.config.getServerUrl()}
/Tracks/AddStepTrack/`,request
.post<number>(`${this.config.getServerUrl()}/Tracks/AddStepTrack/`,request
);
}
......@@ -88,9 +79,7 @@ export class TrackService {
return this
.http
.post<number>(`
${this.config.getServerUrl()}
/Tracks/AddEmployeeTrack/`,request
.post<number>(`${this.config.getServerUrl()}/Tracks/AddEmployeeTrack/`,request
);
}
......@@ -101,9 +90,7 @@ export class TrackService {
return this
.http
.post<void>(`
${this.config.getServerUrl()}
/Tracks/AddStepTrack/`,request
.post<void>(`${this.config.getServerUrl()}/Tracks/AddStepTrack/`,request
);
}
......@@ -113,9 +100,7 @@ export class TrackService {
return this
.http
.post<void>(`
${this.config.getServerUrl()}
/Tracks/RemoveTrack/`,request
.post<void>(`${this.config.getServerUrl()}/Tracks/RemoveTrack/`,request
);
}
......@@ -125,9 +110,7 @@ export class TrackService {
return this
.http
.post<Track>(`
${this.config.getServerUrl()}
/Tracks/AddStepTrack/`,request
.post<Track>(`${this.config.getServerUrl()}/Tracks/`,request
);
}
......@@ -137,9 +120,7 @@ export class TrackService {
return this
.http
.put<void>(`
${this.config.getServerUrl()}
/Tracks/UpdateEmployeeWorkTrack/`,request
.put<void>(`${this.config.getServerUrl()}/Tracks/UpdateEmployeeWorkTrack/`,request
);
}
......@@ -151,9 +132,7 @@ export class TrackService {
return this
.http
.put<void>(`
${this.config.getServerUrl()}
/Tracks/UpdateStepTrack/`,request
.put<void>(`${this.config.getServerUrl()}/Tracks/UpdateStepTrack/`,request
);
}
......
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TracksComponent } from './pages/tracks/tracks.component';
import { TrackDetailsComponent } from './pages/track-details/track-details.component';
const routes: Routes = [];
const routes: Routes = [
{path:'project/:id',component:TracksComponent},
{path:'detail/:id',component:TrackDetailsComponent}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
......
......@@ -4,30 +4,61 @@ import { CommonModule } from '@angular/common';
import { TracksRoutingModule } from './tracks-routing.module';
import { TracksComponent } from './pages/tracks/tracks.component';
import { TrackDetailsComponent } from './pages/track-details/track-details.component';
import { TracCreateComponent } from './pages/trac-create/trac-create.component';
import { StepTrackComponent } from './components/step-track/step-track.component';
import { EmployeeTrackComponent } from './components/employee-track/employee-track.component';
import { StepTrackDetailsComponent } from './pages/step-track-details/step-track-details.component';
import { ProjectTrackHistoryComponent } from './pages/project-track-history/project-track-history.component';
import { StepTrackHistoryComponent } from './pages/step-track-history/step-track-history.component';
import { EmployeeTrackHistoryComponent } from './pages/employee-track-history/employee-track-history.component';
import { TrackCreateComponent } from './pages/track-create/track-create.component';
import { AddTrackModalComponent } from './components/modals/add-track-modal/add-track-modal.component';
import { AddStepTrackModalComponent } from './components/modals/add-step-track-modal/add-step-track-modal.component';
import { AddEmployeeTrackModalComponent } from './components/modals/add-employee-track-modal/add-employee-track-modal.component';
import { TrackItemComponent } from './components/track-item/track-item.component';
import { SharedModule } from '../shared/shared.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatCommonModule, MatOptionModule, provideNativeDateAdapter } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { RouterModule } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
declarations: [
TracksComponent,
TrackDetailsComponent,
TracCreateComponent,
StepTrackComponent,
EmployeeTrackComponent,
StepTrackDetailsComponent,
ProjectTrackHistoryComponent,
StepTrackHistoryComponent,
EmployeeTrackHistoryComponent
EmployeeTrackHistoryComponent,
TrackCreateComponent,
AddTrackModalComponent,
AddStepTrackModalComponent,
AddEmployeeTrackModalComponent,
TrackItemComponent
],
imports: [
CommonModule,
MatFormFieldModule,
MatCommonModule,
MatSelectModule,
MatOptionModule,
MatAutocompleteModule,
MatDatepickerModule,
RouterModule ,
MatInputModule,
ReactiveFormsModule ,
NgbModule,
SharedModule,
FormsModule,
TracksRoutingModule
]
],
providers: [ provideNativeDateAdapter()]
})
export class TracksModule { }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment