Commit f38f0b7c authored by hasan khaddour's avatar hasan khaddour

add project type module

parent 930f3d41
......@@ -47,22 +47,25 @@ export const routes: Routes = [
path: 'projects',
loadChildren: () => import('./projects/projects.module').then(m => m.ProjectsModule)
}
, {
path: 'employees',
loadChildren: () => import('./employees/employees.module').then(m => m.EmployeesModule)
}
, {
path: 'reports',
loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule)
}
, {
path: 'tracks',
loadChildren: () => import('./tracks/tracks.module').then(m => m.TracksModule)
}
}
, {
path: 'employees',
loadChildren: () => import('./employees/employees.module').then(m => m.EmployeesModule)
}
, {
path: 'reports',
loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule)
}
, {
path: 'tracks',
loadChildren: () => import('./tracks/tracks.module').then(m => m.TracksModule)
}
, {
path: 'types',
loadChildren: () => import('./projects-types/projects-types.module').then(m => m.ProjectsTypesModule)
}
]
}
,
{
......
......@@ -32,6 +32,8 @@
</div> <!-- /.card -->
</div> <!-- /.col-12 -->
</div> <!-- .row -->
<div class="modal fade" id="customerModal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
......@@ -90,4 +92,4 @@
</div>
</div>
</div>
</div>
\ No newline at end of file
</div>
<form (ngSubmit)="saveType()">
<div class="row">
<div class="mb-3 col-5 offset-1">
<label for="stepName" class="form-label">اسم النوع </label>
<input type="text" name="stepName" id="stepName" class="form-control" [(ngModel)]="selectedItem.typeName" required>
</div>
<div class="mb-3 col-5 ">
<label for="local" class="form-label">الجهد لهذا النوع من المشاريع</label>
<input id="local" class="form-control" [(ngModel)]="selectedItem.expectedEffort" name="local" required>
</div>
<div class="mb-3 col-9 offset-1">
<label for="typeDescription" class="form-label">وصف هذا النوع</label>
<textarea id="typeDescription" class="form-control" [cols]="3" [(ngModel)]="selectedItem.description" name="typeDescription" required>
</textarea>
</div>
</div>
<button type="submit" class="btn btn-success">حفظ</button>
</form>
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ProjectType } from '../../models/responses/projectType';
@Component({
selector: 'edit-type-modal',
templateUrl: './edit-type-modal.component.html',
styleUrl: './edit-type-modal.component.css'
})
export class EditTypeModalComponent {
@Input() selectedItem : ProjectType
@Output() submit = new EventEmitter<ProjectType>();
constructor(){}
saveType(){
this.submit.emit(this.selectedItem);
}
}
<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">{{item.typeName}}</strong><span class=" ml-1"></span>
</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">وصف هذا النوع من المشاريع : {{item.description}}</span>
</div>
</div>
<div class="col-8 ">
<div class="small mb-2 d-flex">
<span class="text-muted">الجهد المتوقع لهذا النوع من المشاريع {{item.expectedEffort}} ساعة عمل</span>
</div>
<div class="col-auto">
<button type="button" (click)="onEdit()" 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 { ProjectType } from '../../models/responses/projectType';
@Component({
selector: 'type-item',
templateUrl: './type-item.component.html',
styleUrl: './type-item.component.css'
})
export class TypeItemComponent {
@Input() item :ProjectType
@Output() edit = new EventEmitter<void>();
@Output() delete = new EventEmitter<void>();
onEdit() {
this.edit.emit();
}
onDelete() {
this.delete.emit();
}
}
export class CreateNewTypeRequest {
typeName: string;
description: string;
expectedEffort: number;
}
export class UpdateTypeRequest{
id :number
typeName :string
description :String
expectedEffort :number
}
export class ProjectType {
id :number
typeName :string
description :string
expectedEffort :number
}
\ No newline at end of file
<section class="section contact">
<div class="row gy-4">
<div class="col-xl-6 col offset-3">
<div class="card p-4">
<form class="php-email-form">
<div class="row text-center">
<p>
إصافة نوع مشروع
</p>
</div>
<div class="row gy-4">
<div class="col-12">
<input type="text" [(ngModel)]="request.typeName"
name="name" class="form-control" placeholder="اسم المشروع" required>
</div>
<div class="col-6 ">
<textarea type="tex" [(ngModel)]="request.description" [cols]="4" name="description"
class="form-control" name="description" placeholder="الوصف" minlength="15" required>
</textarea>
</div>
<div class="col-6">
<input type="number" [(ngModel)]="request.expectedEffort"
class="form-control" name="subject" placeholder="ساعات العمل اللازمة" required min="0" >
</div>
<div class="col-md-12 text-center">
<button class="btn btn-primary" (click)="submit(request)">إضافة</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
import { Component } from '@angular/core';
import { CreateNewTypeRequest } from '../../models/requests/createNewTypeRequest';
import { ProjectsTypesService } from '../../services/projects-types.service';
import { ToastrService } from 'ngx-toastr';
import { Router } from '@angular/router';
import { CreateCustomerRequest } from '../../../customers/models/createCustomerRequest';
@Component({
selector: 'types-create',
templateUrl: './types-create.component.html',
styleUrl: './types-create.component.css'
})
export class TypesCreateComponent {
request :CreateNewTypeRequest = new CreateNewTypeRequest()
constructor(
private typeService :ProjectsTypesService,
private toastr : ToastrService,
private router : Router
){}
submit(request : CreateNewTypeRequest){
this.typeService.addType(request)
.subscribe({
next : (res)=>{
this.toastr.success("تمت إضافة الجهة بنجاح");
this.router.navigate(['types/detail', res.id]);
}
,
error : (err)=>this.toastr.error("لقد حدث خطاء ما ")
});
}
}
<div class="container-fluid" *ngIf="type">
<div class="row justify-content-center">
<div class="col-8 offset-2 ">
<div class="card shadow">
<div class="card-body">
<div class="col-6 col-sm-12 text-center mb-4">
<img src="/assets/images/users/4.jpg" class="navbar-brand-img brand-sm mx-auto mb-4" alt="...">
<h3 class="mb-0 text-uppercase">{{type.typeName}}</h3>
</div>
</div>
<hr>
<div class="row ml-4">
<p><strong>الوصف</strong></p>
<p> {{type.description}}</p>
<p>عدد ساعات العمل المتوقعة لهذا النوع من المشاريع {{type.expectedEffort}}</p>
</div>
<div class="row mb-4">
<button class="col-3 offset-1 m-4 btn btn-danger" (click)="openModal('delete')">إزالة</button>
<button class="col-3 offset-1 m-4 btn btn-primary" (click)="openModal('edit')">تعديل</button>
</div>
</div> <!-- /.card-body -->
</div> <!-- /.card -->
</div> <!-- /.col-12 -->
<div class="modal fade" id="typeModal" 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="mr-4 ml-4 btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<h5 class="modal-title" id="modalLabel">{{ modalTitle }}</h5>
</div>
<div class="modal-body">
<!-- Edit Form -->
<div *ngIf="modalMode === 'edit'">
<edit-type-modal
[selectedItem]="selectedtype"
(submit)="saveType()"
>
</edit-type-modal>
</div>
<!-- Delete Confirmation -->
<div *ngIf="modalMode === 'delete'">
<p>هل أنت متأكد من أنك تريد حذف النوع {{ selectedtype.typeName }} ؟</p>
<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>
</div>
</div>
</div>
</div> <!-- .row -->
import { Component, OnInit } from '@angular/core';
import { ProjectType } from '../../models/responses/projectType';
import { ProjectsTypesService } from '../../services/projects-types.service';
import { ActivatedRoute, Router } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { Modal } from 'bootstrap';
import { UpdateTypeRequest } from '../../models/requests/updateProjectTypeRequest';
@Component({
selector: 'types-detail',
templateUrl: './types-detail.component.html',
styleUrl: './types-detail.component.css'
})
export class TypesDetailComponent implements OnInit{
type :ProjectType
selectedtype :ProjectType
modalMode: 'edit' | 'delete' = 'edit';
modalTitle: string = '';
constructor(
private typeService : ProjectsTypesService,
private route : ActivatedRoute,
private toastr : ToastrService,
private router : Router
){}
ngOnInit(): void {
const id = Number(this.route.snapshot.paramMap.get('id'));
this.typeService.getTypeById(id).subscribe({
next :(data) => {
this.type = data;
this.selectedtype={...this.type}
},
error : (err)=>{
console.log(err)
this.toastr.error('لقد حدث خطاء ما');
}
});
}
openModal(mode: 'edit' | 'delete'): void {
this.modalMode = mode;
if (mode === 'edit') {
this.modalTitle = 'تعديل نوع مشروع ';
} else if (mode === 'delete') {
this.modalTitle = 'حذف نوع مشروع';
}
const modalElement = document.getElementById('typeModal');
if (modalElement) {
new Modal(modalElement).show(); // Open the modal
}
}
saveType(): void {
let request : UpdateTypeRequest ={
...this.selectedtype,
}
this.typeService.updateType(this.selectedtype.id,request).subscribe({
next :()=>{
this.type={...this.selectedtype};
this.closeModal();
}
,
error:(err)=>{
this.toastr.error("لقد حدث خطاء ما ")
this.closeModal();
}
})
}
delete(): void {
this.typeService.delete(this.type.id).subscribe({
next :()=>{
this.router.navigate(['/types'])
this.closeModal();
}
,
error:(err)=>{
this.toastr.error("لقد حدث خطاء ما ")
this.closeModal();
}
}
);
}
closeModal(): void {
const modalElement = document.getElementById('typeModal');
if (modalElement) {
new Modal(modalElement).hide(); // Close the modal
}
}
}
<section *ngIf="types" 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" [routerLink]="['/types/create']" class="btn btn-primary"><span class="fe fe-file-plus fe-12 mr-2"></span>إضافة عنصر </button>
</div>
</div>
<hr>
<type-item class=" offset-2"
*ngFor="let item of types"
[item]="item"
(edit)="openModal('edit', item)"
(delete)="openModal('delete', item)"
>
</type-item>
<div *ngIf="types.length==0">
للأسف حاليا لايوجد أنواع مشاريع
</div>
</div>
</div>
</section>
<div class="modal fade" id="typeModal" 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">
<!-- Edit Form -->
<div *ngIf="modalMode === 'edit'">
<edit-type-modal
[selectedItem]="selectedItem"
(submit)="saveType()"
></edit-type-modal>
</div>
<!-- Delete Confirmation -->
<div *ngIf="modalMode === 'delete'">
<p>هل أنت متأكد من أنك تريد حذف عنصر {{ selectedItem.typeName }}?</p>
<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>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
import { ProjectsTypesService } from '../../services/projects-types.service';
import { ToastrService } from 'ngx-toastr';
import { ActivatedRoute, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Modal } from 'bootstrap';
import { ProjectType } from '../../models/responses/projectType';
import { UpdateTypeRequest } from '../../models/requests/updateProjectTypeRequest';
@Component({
selector: 'types-list',
templateUrl: './types-list.component.html',
styleUrl: './types-list.component.css'
})
export class TypesListComponent {
types :ProjectType[]
selectedItem : ProjectType;
modalMode: 'edit' | 'delete' = 'edit';
modalTitle: string = '';
constructor(
private typeService : ProjectsTypesService,
private toastr : ToastrService,
private route: ActivatedRoute,
public router :Router,
private modalService: NgbModal
) {
}
ngOnInit(): void {
this.loadTypes();
this.selectedItem =new ProjectType();
}
loadTypes(): void{
this.typeService.getAllTypes().subscribe({
next: (data)=> {
this.types= data
this.toastr.success("تم تحميل أنواع المشاريع بنجاح");
}
,
error:(err)=>{
console.log(err)
this.toastr.error("لقد حدث خطاء ما")
}
})
}
openModal(mode: 'edit' | 'delete', item: ProjectType): 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('typeModal');
if (modalElement) {
new Modal(modalElement).show(); // Open the modal
}
}
saveType(): void {
let request : UpdateTypeRequest ={
...this.selectedItem,
}
this.typeService.updateType(this.selectedItem.id,request).subscribe({
next :()=>{
const index = this.types.findIndex(p => p.id === this.selectedItem.id);
if (index !== -1) {
this.types[index] = this.selectedItem;
}
this.closeModal();
}
,
error:(err)=>{
this.toastr.error("لقد حدث خطاء ما ")
this.closeModal();
}
})
this.closeModal();
}
delete(): void {
this.typeService.delete(this.selectedItem.id).subscribe({
next :()=>{
this.types = this.types.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('typeModal');
if (modalElement) {
new Modal(modalElement).hide(); // Close the modal
}
}
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TypesCreateComponent } from './pages/types-create/types-create.component';
import { TypesDetailComponent } from './pages/types-detail/types-detail.component';
import { TypesListComponent } from './pages/types-list/types-list.component';
const routes: Routes = [
{path:'create',component:TypesCreateComponent},
{path:'detail/:id',component:TypesDetailComponent},
{path:'',component:TypesListComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ProjectsTypesRoutingModule { }
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProjectsTypesRoutingModule } from './projects-types-routing.module';
import { TypeItemComponent } from './components/type-item/type-item.component';
import { TypesListComponent } from './pages/types-list/types-list.component';
import { TypesCreateComponent } from './pages/types-create/types-create.component';
import { EditTypeModalComponent } from './components/edit-type-modal/edit-type-modal.component';
import { FormsModule } from '@angular/forms';
import { TypesDetailComponent } from './pages/types-detail/types-detail.component';
@NgModule({
declarations: [
TypeItemComponent,
TypesListComponent,
TypesCreateComponent,
EditTypeModalComponent,
TypesDetailComponent
],
imports: [
CommonModule,
FormsModule,
ProjectsTypesRoutingModule
]
})
export class ProjectsTypesModule { }
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ConfigurationService } from '../../core/services/configuration/configuration.service';
import { ProjectType } from '../models/responses/projectType';
import { Observable } from 'rxjs';
import { CreateNewTypeRequest } from '../models/requests/createNewTypeRequest';
import { UpdateTypeRequest } from '../models/requests/updateProjectTypeRequest';
@Injectable({
providedIn: 'root'
})
export class ProjectsTypesService {
constructor(private http :HttpClient ,private config : ConfigurationService) { }
public getAllTypes():Observable<ProjectType[]>{
return this
.http
.get<ProjectType[]>
(this.config.getServerUrl()+ "/ProjectsTypes");
}
public getTypeById(typeId : number ):Observable<ProjectType>{
return this
.http
.get<ProjectType>
(this.config.getServerUrl()+ "/ProjectsTypes/"+typeId);
}
public addType(request : CreateNewTypeRequest):Observable<ProjectType>{
return this
.http
.post<ProjectType>
(this.config.getServerUrl()+ "/ProjectsTypes/",request);
}
public delete(typeId : number ):Observable<void>{
return this
.http
.delete<void>
(this.config.getServerUrl()+ "/ProjectsTypes"+typeId);
}
public updateType(typeId : number , request : UpdateTypeRequest):Observable<void>{
return this
.http
.put<void>
(this.config.getServerUrl()+ "/ProjectsTypes/"+typeId,request);
}
}
......@@ -35,6 +35,17 @@
<i class="fe fe-flag"></i><span> عمليات المتابعة</span>
</a>
</li>
<li class="nav-heading">أنواع المشاريع</li>
<li class="nav-item">
<a [routerLink]="['/types']" class="nav-link collapsed ">
<i class="fe fe-map"></i><span> استعراض أنواع المشاريع</span>
</a>
</li>
<li class="nav-item">
<a [routerLink]="['/types/create']" class="nav-link collapsed " >
<i class="fe fe-edit-2"></i><span>إضافة نوع جديد</span>
</a>
</li>
<li class="nav-heading">التقارير</li>
......
......@@ -10,11 +10,11 @@ import { Modal } from 'bootstrap';
import { RemoveTrackRequest } from '../../models/requests/RemoveTrackRequest';
@Component({
selector: 'tracks',
templateUrl: './tracks.component.html',
styleUrl: './tracks.component.css'
selector: 'tracks-list',
templateUrl: './tracks-list.component.html',
styleUrl: './tracks-list.component.css'
})
export class TracksComponent implements OnInit{
export class TracksListComponent implements OnInit{
projectId : number
tracks : Track[]
......
import { Component } from '@angular/core';
@Component({
selector: 'tracks-uncomplete',
templateUrl: './tracks-uncomplete.component.html',
styleUrl: './tracks-uncomplete.component.css'
})
export class TracksUncompleteComponent {
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TracksComponent } from './pages/tracks/tracks.component';
import { TracksListComponent } from './pages/tracks-list/tracks-list.component';
import { TrackDetailsComponent } from './pages/track-details/track-details.component';
import { StepTrackHistoryComponent } from './pages/step-track-history/step-track-history.component';
import { EmployeeTrackHistoryComponent } from './pages/employee-track-history/employee-track-history.component';
const routes: Routes = [
{path:'project/:id',component:TracksComponent},
{path:'project/:id',component:TracksListComponent},
{path:'detail/:id',component:TrackDetailsComponent},
{path:'history/step/:id',component:StepTrackHistoryComponent} ,
{path:'project/:projectId/employee/:employeeId',component:EmployeeTrackHistoryComponent}
......
......@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TracksRoutingModule } from './tracks-routing.module';
import { TracksComponent } from './pages/tracks/tracks.component';
import { TracksListComponent } from './pages/tracks-list/tracks-list.component';
import { TrackDetailsComponent } from './pages/track-details/track-details.component';
import { StepTrackComponent } from './components/step-track/step-track.component';
import { EmployeeTrackComponent } from './components/employee-track/employee-track.component';
......@@ -26,11 +26,12 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { StepHistoryItemComponent } from './components/history/step-history-item/step-history-item.component';
import { EmployeeHistoryItemComponent } from './components/history/employee-history-item/employee-history-item.component';
import { StateTranslatePipe } from '../shared/pipes/stateTranslate/state-translate.pipe';
import { TracksUncompleteComponent } from './pages/tracks-uncomplete/tracks-uncomplete.component';
@NgModule({
declarations: [
TracksComponent,
TracksListComponent,
TrackDetailsComponent,
StepTrackComponent,
EmployeeTrackComponent,
......@@ -42,7 +43,8 @@ import { StateTranslatePipe } from '../shared/pipes/stateTranslate/state-transla
AddEmployeeTrackModalComponent,
TrackItemComponent,
StepHistoryItemComponent,
EmployeeHistoryItemComponent
EmployeeHistoryItemComponent,
TracksUncompleteComponent
],
imports: [
CommonModule,
......
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