feat(giving): giving categories management page
Add GivingCategoriesPageComponent — standalone Angular 18 component with Kendo Grid (list/deactivate) and Kendo Dialog (add/edit form) for managing giving types. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
<div class="page">
|
||||
<header class="page-header">
|
||||
<h2>Giving Types / 奉獻類型</h2>
|
||||
<div class="header-actions">
|
||||
<label class="inactive-toggle">
|
||||
<input type="checkbox" [(ngModel)]="includeInactive" (change)="load()" /> Show inactive
|
||||
</label>
|
||||
<button kendoButton themeColor="primary" (click)="openAdd()">+ Add</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<kendo-grid [data]="data" [loading]="isLoading">
|
||||
<kendo-grid-column field="sortOrder" title="#" [width]="60"></kendo-grid-column>
|
||||
<kendo-grid-column field="name_en" title="Name (EN)"></kendo-grid-column>
|
||||
<kendo-grid-column field="name_zh" title="名稱 (中)"></kendo-grid-column>
|
||||
<kendo-grid-column field="isActive" title="Active" [width]="90">
|
||||
<ng-template kendoGridCellTemplate let-c>{{ c.isActive ? 'Yes' : 'No' }}</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column title="Actions" [width]="160">
|
||||
<ng-template kendoGridCellTemplate let-c>
|
||||
<button kendoButton fillMode="flat" (click)="openEdit(c)">Edit</button>
|
||||
<button kendoButton fillMode="flat" *ngIf="c.isActive" (click)="deactivate(c)">Deactivate</button>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
|
||||
<kendo-dialog *ngIf="showDialog" [title]="editing ? 'Edit Giving Type' : 'Add Giving Type'" (close)="showDialog=false" [width]="480">
|
||||
<div class="form-grid">
|
||||
<label>
|
||||
Name (EN) *
|
||||
<kendo-textbox [(ngModel)]="form.name_en"></kendo-textbox>
|
||||
</label>
|
||||
<label>
|
||||
名稱 (中)
|
||||
<kendo-textbox [(ngModel)]="form.name_zh"></kendo-textbox>
|
||||
</label>
|
||||
<label>
|
||||
Description (EN)
|
||||
<kendo-textbox [(ngModel)]="form.description_en"></kendo-textbox>
|
||||
</label>
|
||||
<label>
|
||||
說明 (中)
|
||||
<kendo-textbox [(ngModel)]="form.description_zh"></kendo-textbox>
|
||||
</label>
|
||||
<label>
|
||||
Sort order
|
||||
<kendo-numerictextbox [(ngModel)]="form.sortOrder" [format]="'n0'" [decimals]="0" [min]="0"></kendo-numerictextbox>
|
||||
</label>
|
||||
<label *ngIf="editing">
|
||||
<input type="checkbox" [(ngModel)]="form.isActive" /> Active
|
||||
</label>
|
||||
</div>
|
||||
<kendo-dialog-actions>
|
||||
<button kendoButton (click)="showDialog=false">Cancel</button>
|
||||
<button kendoButton themeColor="primary" [disabled]="!form.name_en" (click)="save()">Save</button>
|
||||
</kendo-dialog-actions>
|
||||
</kendo-dialog>
|
||||
</div>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.inactive-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.form-grid label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { GridModule } from '@progress/kendo-angular-grid';
|
||||
import { InputsModule } from '@progress/kendo-angular-inputs';
|
||||
import { ButtonsModule } from '@progress/kendo-angular-buttons';
|
||||
import { DialogsModule } from '@progress/kendo-angular-dialog';
|
||||
import { GivingCategoryApiService } from '../../services/giving-category-api.service';
|
||||
import {
|
||||
GivingCategoryDto, CreateGivingCategoryRequest, UpdateGivingCategoryRequest,
|
||||
} from '../../models/giving.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-giving-categories-page',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule, GridModule, InputsModule, ButtonsModule, DialogsModule],
|
||||
templateUrl: './giving-categories-page.component.html',
|
||||
styleUrls: ['./giving-categories-page.component.scss'],
|
||||
})
|
||||
export class GivingCategoriesPageComponent implements OnInit {
|
||||
data: GivingCategoryDto[] = [];
|
||||
isLoading = false;
|
||||
includeInactive = false;
|
||||
|
||||
showDialog = false;
|
||||
editing: GivingCategoryDto | null = null;
|
||||
form: UpdateGivingCategoryRequest = this.blankForm();
|
||||
|
||||
constructor(private api: GivingCategoryApiService) {}
|
||||
|
||||
ngOnInit(): void { this.load(); }
|
||||
|
||||
load(): void {
|
||||
this.isLoading = true;
|
||||
this.api.getAll(this.includeInactive).subscribe({
|
||||
next: rows => { this.data = rows; this.isLoading = false; },
|
||||
error: () => { this.isLoading = false; },
|
||||
});
|
||||
}
|
||||
|
||||
openAdd(): void { this.editing = null; this.form = this.blankForm(); this.showDialog = true; }
|
||||
|
||||
openEdit(c: GivingCategoryDto): void {
|
||||
this.editing = c;
|
||||
this.form = {
|
||||
name_en: c.name_en, name_zh: c.name_zh,
|
||||
description_en: c.description_en, description_zh: c.description_zh,
|
||||
isActive: c.isActive, sortOrder: c.sortOrder,
|
||||
};
|
||||
this.showDialog = true;
|
||||
}
|
||||
|
||||
save(): void {
|
||||
if (this.editing) {
|
||||
this.api.update(this.editing.id, this.form).subscribe(() => { this.showDialog = false; this.load(); });
|
||||
} else {
|
||||
const create: CreateGivingCategoryRequest = {
|
||||
name_en: this.form.name_en, name_zh: this.form.name_zh,
|
||||
description_en: this.form.description_en, description_zh: this.form.description_zh,
|
||||
sortOrder: this.form.sortOrder,
|
||||
};
|
||||
this.api.create(create).subscribe(() => { this.showDialog = false; this.load(); });
|
||||
}
|
||||
}
|
||||
|
||||
deactivate(c: GivingCategoryDto): void {
|
||||
if (!confirm(`Deactivate "${c.name_en}"?`)) return;
|
||||
this.api.deactivate(c.id).subscribe(() => this.load());
|
||||
}
|
||||
|
||||
private blankForm(): UpdateGivingCategoryRequest {
|
||||
return { name_en: '', name_zh: null, description_en: null, description_zh: null, isActive: true, sortOrder: 0 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user