poprawki
This commit is contained in:
@@ -6,9 +6,17 @@ import { CategoriesService } from '../../core/services/categories.service';
|
||||
import { ExpensesService } from '../../core/services/expenses.service';
|
||||
import { MerchantsService } from '../../core/services/merchants.service';
|
||||
import { ToastService } from '../../core/services/toast.service';
|
||||
import { UiService } from '../../core/services/ui.service';
|
||||
import type { Expense, Merchant, Proof } from '../../shared/models';
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const formatLocalDate = (date: Date) => {
|
||||
const year = date.getFullYear();
|
||||
const month = `${date.getMonth() + 1}`.padStart(2, '0');
|
||||
const day = `${date.getDate()}`.padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
const today = formatLocalDate(new Date());
|
||||
|
||||
@Component({
|
||||
selector: 'app-expenses',
|
||||
@@ -18,8 +26,8 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="page-header d-print-none mb-3 ec-page-header">
|
||||
<div class="row align-items-center g-3">
|
||||
<div class="col">
|
||||
<h2 class="page-title mb-1">Wydatki</h2>
|
||||
<div class="text-secondary">Dodawaj wydatki, zapisuj potwierdzenia i wybieraj kontrahentów z listy.</div>
|
||||
<h2 class="page-title mb-1">{{ ui.t('expenses.title') }}</h2>
|
||||
<div class="text-secondary">{{ ui.t('expenses.subtitle') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,64 +36,80 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="col-xl-7">
|
||||
<div class="card overflow-hidden">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h3 class="card-title">{{ editingExpenseId() ? 'Edytuj wydatek' : 'Nowy wydatek' }}</h3>
|
||||
<h3 class="card-title">{{ editingExpenseId() ? ui.t('expenses.edit') : ui.t('expenses.new') }}</h3>
|
||||
@if (editingExpenseId()) {
|
||||
<button class="btn btn-outline-secondary btn-sm" type="button" (click)="cancelEdit()">Anuluj edycję</button>
|
||||
<button class="btn btn-outline-secondary btn-sm" type="button" (click)="cancelEdit()">{{ ui.t('action.cancelEdit') }}</button>
|
||||
}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form [formGroup]="expenseForm" (ngSubmit)="submitExpense()" class="d-grid gap-3">
|
||||
<form [formGroup]="expenseForm" (ngSubmit)="submitExpense()" class="d-grid gap-3" novalidate>
|
||||
@if (submitted() && expenseForm.invalid) {
|
||||
<div class="alert alert-danger mb-0">{{ ui.t('expenses.requiredHint') }}</div>
|
||||
}
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-7">
|
||||
<label class="form-label">Tytuł</label>
|
||||
<input class="form-control" formControlName="title" />
|
||||
<label class="form-label">{{ ui.t('expenses.field.title') }} <span class="text-danger">*</span></label>
|
||||
<input class="form-control" formControlName="title" [class.is-invalid]="expenseForm.controls.title.invalid && (expenseForm.controls.title.touched || submitted())" />
|
||||
@if (expenseForm.controls.title.invalid && (expenseForm.controls.title.touched || submitted())) {
|
||||
<div class="invalid-feedback d-block">{{ ui.t('expenses.validation.title') }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Kwota</label>
|
||||
<input class="form-control" type="number" step="0.01" formControlName="amount" />
|
||||
<label class="form-label">{{ ui.t('expenses.field.amount') }} <span class="text-danger">*</span></label>
|
||||
<input class="form-control" type="number" step="0.01" formControlName="amount" [class.is-invalid]="expenseForm.controls.amount.invalid && (expenseForm.controls.amount.touched || submitted())" />
|
||||
@if (expenseForm.controls.amount.invalid && (expenseForm.controls.amount.touched || submitted())) {
|
||||
<div class="invalid-feedback d-block">{{ ui.t('expenses.validation.amount') }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Data</label>
|
||||
<input class="form-control" type="date" formControlName="expenseDate" />
|
||||
<label class="form-label">{{ ui.t('expenses.field.date') }} <span class="text-danger">*</span></label>
|
||||
<input class="form-control" type="date" formControlName="expenseDate" [class.is-invalid]="expenseForm.controls.expenseDate.invalid && (expenseForm.controls.expenseDate.touched || submitted())" />
|
||||
@if (expenseForm.controls.expenseDate.invalid && (expenseForm.controls.expenseDate.touched || submitted())) {
|
||||
<div class="invalid-feedback d-block">{{ ui.t('expenses.validation.date') }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Kategoria</label>
|
||||
<select class="form-select" formControlName="categoryId">
|
||||
<option value="">Wybierz</option>
|
||||
<label class="form-label">{{ ui.t('expenses.field.category') }} <span class="text-danger">*</span></label>
|
||||
<select class="form-select" formControlName="categoryId" [class.is-invalid]="expenseForm.controls.categoryId.invalid && (expenseForm.controls.categoryId.touched || submitted())">
|
||||
<option value="">{{ ui.t('common.select') }}</option>
|
||||
@for (category of categories(); track category.id) {
|
||||
<option [value]="category.id">{{ category.name }}</option>
|
||||
}
|
||||
</select>
|
||||
@if (expenseForm.controls.categoryId.invalid && (expenseForm.controls.categoryId.touched || submitted())) {
|
||||
<div class="invalid-feedback d-block">{{ ui.t('expenses.validation.category') }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Płatność</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.payment') }}</label>
|
||||
<select class="form-select" formControlName="paymentMethod">
|
||||
<option value="">Brak</option>
|
||||
<option value="CARD">Karta</option>
|
||||
<option value="CASH">Gotówka</option>
|
||||
<option value="TRANSFER">Przelew</option>
|
||||
<option value="">{{ ui.t('expenses.payment.none') }}</option>
|
||||
<option value="CARD">{{ ui.t('expenses.payment.card') }}</option>
|
||||
<option value="CASH">{{ ui.t('expenses.payment.cash') }}</option>
|
||||
<option value="TRANSFER">{{ ui.t('expenses.payment.transfer') }}</option>
|
||||
<option value="BLIK">BLIK</option>
|
||||
<option value="OTHER">Inne</option>
|
||||
<option value="OTHER">{{ ui.t('expenses.payment.other') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-label">Kontrahent</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.merchantPicker') }}</label>
|
||||
<div class="input-group">
|
||||
<select class="form-select" [value]="selectedMerchantId()" (change)="selectMerchant($any($event.target).value)">
|
||||
<option value="">Własny wpis</option>
|
||||
<option value="">{{ ui.t('expenses.customEntry') }}</option>
|
||||
@for (item of activeMerchants(); track item.id) {
|
||||
<option [value]="item.id">{{ item.name }}</option>
|
||||
}
|
||||
</select>
|
||||
<button class="btn btn-outline-primary" type="button" (click)="openMerchantModal()">Dodaj</button>
|
||||
<button class="btn btn-outline-primary" type="button" (click)="openMerchantModal()">{{ ui.t('action.add') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Nazwa w wydatku</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.merchantName') }}</label>
|
||||
<input class="form-control" formControlName="merchant" />
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">Opis</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.description') }}</label>
|
||||
<textarea class="form-control" rows="3" formControlName="description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,49 +119,49 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="card-body d-grid gap-3">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Typ potwierdzenia</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.proofType') }}</label>
|
||||
<select class="form-select" formControlName="proofType">
|
||||
<option value="RECEIPT">Paragon</option>
|
||||
<option value="INVOICE">Faktura</option>
|
||||
<option value="NOTE">Notatka</option>
|
||||
<option value="BANK_STATEMENT">Wyciąg</option>
|
||||
<option value="OTHER">Inne</option>
|
||||
<option value="RECEIPT">{{ ui.t('proof.receipt') }}</option>
|
||||
<option value="INVOICE">{{ ui.t('proof.invoice') }}</option>
|
||||
<option value="NOTE">{{ ui.t('proof.note') }}</option>
|
||||
<option value="BANK_STATEMENT">{{ ui.t('proof.statement') }}</option>
|
||||
<option value="OTHER">{{ ui.t('proof.other') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Etykieta</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.proofLabel') }}</label>
|
||||
<input class="form-control" formControlName="proofLabel" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Plik</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.file') }}</label>
|
||||
<input class="form-control" type="file" accept="image/*,.pdf" (change)="onProofSelected($event)" />
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">Notatka do potwierdzenia</label>
|
||||
<label class="form-label">{{ ui.t('expenses.field.proofNote') }}</label>
|
||||
<textarea class="form-control" rows="2" formControlName="proofNote"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (showCropper()) {
|
||||
<div>
|
||||
<div class="form-label">Kadrowanie</div>
|
||||
<div class="form-label">{{ ui.t('expenses.field.crop') }}</div>
|
||||
<image-cropper [imageChangedEvent]="imageChangedEvent()" [maintainAspectRatio]="false" format="png" (imageCropped)="onImageCropped($event)"></image-cropper>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (croppedPreview()) {
|
||||
<div>
|
||||
<div class="form-label">Podgląd po cropie</div>
|
||||
<img class="img-fluid rounded" [src]="croppedPreview()" alt="Podgląd" />
|
||||
<div class="form-label">{{ ui.t('expenses.field.cropPreview') }}</div>
|
||||
<img class="img-fluid rounded" [src]="croppedPreview()" [alt]="ui.t('expenses.field.cropPreview')" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button class="btn btn-success d-inline-flex align-items-center justify-content-center gap-2" [disabled]="expenseForm.invalid || saving()">
|
||||
<button class="btn btn-success d-inline-flex align-items-center justify-content-center gap-2" [disabled]="saving()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l5 5l10 -10"/></svg>
|
||||
<span>{{ saving() ? 'Zapisywanie...' : (editingExpenseId() ? 'Zapisz zmiany' : 'Dodaj wydatek') }}</span>
|
||||
<span>{{ saving() ? ui.t('expenses.saving') : (editingExpenseId() ? ui.t('action.saveChanges') : ui.t('action.addExpense')) }}</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -146,23 +170,23 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
<div class="col-xl-5">
|
||||
<div class="card sticky-top overflow-hidden" style="top: 1rem;">
|
||||
<div class="card-header"><h3 class="card-title">Filtry i ostatnie wydatki</h3></div>
|
||||
<div class="card-header"><h3 class="card-title">{{ ui.t('expenses.filters') }}</h3></div>
|
||||
<div class="card-body">
|
||||
<form [formGroup]="filterForm" (ngSubmit)="loadExpenses()" class="row g-2 mb-4">
|
||||
<div class="col-6"><input class="form-control" type="date" formControlName="startDate" /></div>
|
||||
<div class="col-6"><input class="form-control" type="date" formControlName="endDate" /></div>
|
||||
<div class="col-12">
|
||||
<select class="form-select" formControlName="categoryId">
|
||||
<option value="">Wszystkie kategorie</option>
|
||||
<option value="">{{ ui.t('expenses.allCategories') }}</option>
|
||||
@for (category of categories(); track category.id) {
|
||||
<option [value]="category.id">{{ category.name }}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12"><input class="form-control" formControlName="search" placeholder="Szukaj" /></div>
|
||||
<div class="col-12"><input class="form-control" formControlName="search" [placeholder]="ui.t('expenses.search')" /></div>
|
||||
<div class="col-12 d-flex gap-2">
|
||||
<button class="btn btn-primary flex-fill">Filtruj</button>
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="resetFilters()">Reset</button>
|
||||
<button class="btn btn-primary flex-fill">{{ ui.t('action.filter') }}</button>
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="resetFilters()">{{ ui.t('action.reset') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -173,14 +197,14 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="d-flex justify-content-between gap-3">
|
||||
<div>
|
||||
<div class="fw-semibold">{{ expense.title }}</div>
|
||||
<div class="small text-secondary">{{ expense.merchant || 'Brak kontrahenta' }} • {{ expense.expenseDate | date:'shortDate' }}</div>
|
||||
<div class="small text-secondary">{{ expense.merchant || ui.t('expenses.noMerchant') }} • {{ expense.expenseDate | date:'shortDate' }}</div>
|
||||
<div class="small text-secondary">{{ expense.category.name }}</div>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<div class="fw-bold">{{ expense.amount | currency:expense.currency:'symbol':'1.2-2' }}</div>
|
||||
<div class="btn-list justify-content-end mt-2">
|
||||
<button class="btn btn-outline-primary btn-sm" type="button" (click)="startEdit(expense)">Edytuj</button>
|
||||
<button class="btn btn-outline-danger btn-sm" type="button" (click)="removeExpense(expense)">Usuń</button>
|
||||
<button class="btn btn-outline-primary btn-sm" type="button" (click)="startEdit(expense)">{{ ui.t('action.edit') }}</button>
|
||||
<button class="btn btn-outline-danger btn-sm" type="button" (click)="removeExpense(expense)">{{ ui.t('action.delete') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,7 +212,7 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="btn-list mt-3">
|
||||
@for (proof of expense.proofs; track proof.id) {
|
||||
<button class="btn btn-outline-info btn-sm" type="button" (click)="openProof(proof)">
|
||||
{{ proof.label || proof.originalName || 'Potwierdzenie' }}
|
||||
{{ proof.label || proof.originalName || ui.t('expenses.proof') }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -197,7 +221,7 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
}
|
||||
</div>
|
||||
} @else {
|
||||
<div class="alert alert-warning mb-0">Brak wydatków do wyświetlenia.</div>
|
||||
<div class="alert alert-warning mb-0">{{ ui.t('expenses.noItems') }}</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -209,33 +233,33 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Nowy kontrahent</h5>
|
||||
<h5 class="modal-title">{{ ui.t('merchant.new') }}</h5>
|
||||
<button class="btn-close" type="button" (click)="closeMerchantModal()"></button>
|
||||
</div>
|
||||
<form [formGroup]="merchantForm" (ngSubmit)="saveMerchant()">
|
||||
<div class="modal-body">
|
||||
<div class="d-grid gap-3">
|
||||
<div>
|
||||
<label class="form-label">Nazwa</label>
|
||||
<label class="form-label">{{ ui.t('merchant.name') }}</label>
|
||||
<input class="form-control" formControlName="name" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Typ</label>
|
||||
<label class="form-label">{{ ui.t('merchant.type') }}</label>
|
||||
<select class="form-select" formControlName="kind">
|
||||
<option value="MERCHANT">Sprzedawca</option>
|
||||
<option value="SERVICE_PROVIDER">Usługodawca</option>
|
||||
<option value="OTHER">Inny</option>
|
||||
<option value="MERCHANT">{{ ui.t('merchant.kind.merchant') }}</option>
|
||||
<option value="SERVICE_PROVIDER">{{ ui.t('merchant.kind.service') }}</option>
|
||||
<option value="OTHER">{{ ui.t('merchant.kind.other') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Notatki</label>
|
||||
<label class="form-label">{{ ui.t('merchant.notes') }}</label>
|
||||
<textarea class="form-control" rows="3" formControlName="notes"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-ghost-secondary" type="button" (click)="closeMerchantModal()">Anuluj</button>
|
||||
<button class="btn btn-success" [disabled]="merchantForm.invalid">Zapisz kontrahenta</button>
|
||||
<button class="btn btn-ghost-secondary" type="button" (click)="closeMerchantModal()">{{ ui.t('action.cancel') }}</button>
|
||||
<button class="btn btn-success" [disabled]="merchantForm.invalid">{{ ui.t('action.saveMerchant') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -249,14 +273,14 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ proofPreview()?.label || proofPreview()?.originalName || 'Potwierdzenie' }}</h5>
|
||||
<h5 class="modal-title">{{ proofPreview()?.label || proofPreview()?.originalName || ui.t('expenses.proof') }}</h5>
|
||||
<button class="btn-close" type="button" (click)="closeProofPreview()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if ((proofPreview()?.mimeType || '').includes('pdf')) {
|
||||
<embed [attr.src]="proofPreview()?.fileUrl" type="application/pdf" style="width:100%;height:75vh;" />
|
||||
} @else {
|
||||
<img class="img-fluid" [src]="proofPreview()?.fileUrl" alt="Potwierdzenie" />
|
||||
<img class="img-fluid" [src]="proofPreview()?.fileUrl" [alt]="ui.t('expenses.proof')" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -267,6 +291,7 @@ const today = new Date().toISOString().slice(0, 10);
|
||||
`
|
||||
})
|
||||
export class ExpensesComponent implements OnInit {
|
||||
readonly ui = inject(UiService);
|
||||
private readonly fb = inject(FormBuilder);
|
||||
private readonly categoriesService = inject(CategoriesService);
|
||||
private readonly merchantsService = inject(MerchantsService);
|
||||
@@ -279,6 +304,7 @@ export class ExpensesComponent implements OnInit {
|
||||
readonly selectedMerchantId = signal('');
|
||||
readonly editingExpenseId = signal<string | null>(null);
|
||||
readonly saving = signal(false);
|
||||
readonly submitted = signal(false);
|
||||
readonly merchantModalOpen = signal(false);
|
||||
readonly proofPreview = signal<Proof | null>(null);
|
||||
|
||||
@@ -289,7 +315,7 @@ export class ExpensesComponent implements OnInit {
|
||||
|
||||
readonly expenseForm = this.fb.nonNullable.group({
|
||||
title: ['', [Validators.required, Validators.minLength(2)]],
|
||||
amount: [0],
|
||||
amount: [0, [Validators.required, Validators.min(0.01)]],
|
||||
expenseDate: [today, Validators.required],
|
||||
categoryId: ['', Validators.required],
|
||||
merchant: [''],
|
||||
@@ -349,12 +375,12 @@ export class ExpensesComponent implements OnInit {
|
||||
if (this.merchantForm.invalid) return;
|
||||
this.merchantsService.create({ ...this.merchantForm.getRawValue(), isActive: true }).subscribe({
|
||||
next: (response) => {
|
||||
this.toast.success('Kontrahent został dodany.');
|
||||
this.toast.success(this.ui.t('merchant.added'));
|
||||
this.merchantModalOpen.set(false);
|
||||
this.selectedMerchantId.set(response.item.id);
|
||||
this.expenseForm.patchValue({ merchant: response.item.name });
|
||||
},
|
||||
error: (error) => this.toast.error(error.error?.message ?? 'Nie udało się dodać kontrahenta.')
|
||||
error: (error) => this.toast.error(error.error?.message ?? this.ui.t('merchant.saveError'))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -380,7 +406,12 @@ export class ExpensesComponent implements OnInit {
|
||||
}
|
||||
|
||||
submitExpense() {
|
||||
this.submitted.set(true);
|
||||
this.expenseForm.markAllAsTouched();
|
||||
this.expenseForm.updateValueAndValidity();
|
||||
|
||||
if (this.expenseForm.invalid) return;
|
||||
|
||||
const raw = this.expenseForm.getRawValue();
|
||||
this.saving.set(true);
|
||||
|
||||
@@ -399,13 +430,14 @@ export class ExpensesComponent implements OnInit {
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.saving.set(false);
|
||||
this.toast.success('Wydatek został zapisany.');
|
||||
this.submitted.set(false);
|
||||
this.toast.success(this.ui.t('expenses.saved'));
|
||||
this.cancelEdit();
|
||||
this.loadExpenses();
|
||||
},
|
||||
error: (error) => {
|
||||
this.saving.set(false);
|
||||
this.toast.error(error.error?.message ?? 'Nie udało się zapisać wydatku.');
|
||||
this.toast.error(error.error?.message ?? this.ui.t('expenses.saveError'));
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -428,7 +460,8 @@ export class ExpensesComponent implements OnInit {
|
||||
this.expensesService.create(formData).subscribe({
|
||||
next: () => {
|
||||
this.saving.set(false);
|
||||
this.toast.success('Wydatek został dodany.');
|
||||
this.submitted.set(false);
|
||||
this.toast.success(this.ui.t('expenses.added'));
|
||||
this.expenseForm.reset({
|
||||
title: '',
|
||||
amount: 0,
|
||||
@@ -449,13 +482,14 @@ export class ExpensesComponent implements OnInit {
|
||||
},
|
||||
error: (error) => {
|
||||
this.saving.set(false);
|
||||
this.toast.error(error.error?.message ?? 'Nie udało się dodać wydatku.');
|
||||
this.toast.error(error.error?.message ?? this.ui.t('expenses.addError'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startEdit(item: Expense) {
|
||||
this.editingExpenseId.set(item.id);
|
||||
this.submitted.set(false);
|
||||
this.expenseForm.patchValue({
|
||||
title: item.title,
|
||||
amount: item.amount,
|
||||
@@ -469,6 +503,7 @@ export class ExpensesComponent implements OnInit {
|
||||
|
||||
cancelEdit() {
|
||||
this.editingExpenseId.set(null);
|
||||
this.submitted.set(false);
|
||||
this.expenseForm.reset({
|
||||
title: '',
|
||||
amount: 0,
|
||||
@@ -486,10 +521,10 @@ export class ExpensesComponent implements OnInit {
|
||||
removeExpense(item: Expense) {
|
||||
this.expensesService.delete(item.id).subscribe({
|
||||
next: () => {
|
||||
this.toast.success('Wydatek został usunięty.');
|
||||
this.toast.success(this.ui.t('expenses.deleted'));
|
||||
this.loadExpenses();
|
||||
},
|
||||
error: (error) => this.toast.error(error.error?.message ?? 'Nie udało się usunąć wydatku.')
|
||||
error: (error) => this.toast.error(error.error?.message ?? this.ui.t('expenses.deleteError'))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user