Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Component, Input, OnInit, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NbDateService } from '@nebular/theme';
import { Calendar } from '../../../../api/objects/calendar';
import { Category } from '../../../../api/objects/category';
import { User } from '../../../../api/objects/user';
import { DateUtil } from '../../../../util/date.util';
import { MainService } from '../../main.service';
import { CalendarComponent } from '../../calendar/calendar.component';

@Component({
selector: 'app-calendar-state',
template: `
<app-calendar
[calendar]="mainService.calendar"
[expenses]="mainService.expenses"
[expenseBalances]="mainService.expenseBalances"
[visibleDate]="mainService.visibleDate"
[selectedDate]="mainService.visibleDate"
(rangeChange)="onRangeChange($event)"
[isMobile]="isMobile">
</app-calendar>
`,
imports: [CalendarComponent],
})
export class CalendarStateComponent implements OnInit {
@Input() public isMobile: boolean;

private readonly activatedRoute = inject(ActivatedRoute);
private readonly router = inject(Router);
private readonly dateService = inject<NbDateService<Date>>(NbDateService);
public readonly mainService = inject(MainService);

public ngOnInit(): void {
this.activatedRoute.data.subscribe(
({
user,
calendars,
systemCategories,
}: {
user: User;
calendars: Calendar[];
systemCategories: Category[];
}) => {
this.mainService.user = user;
this.mainService.calendars = calendars;
this.mainService.systemCategories = systemCategories;
this.mainService.calendar =
this.mainService.calendars.filter((calendar: Calendar) => {
return calendar.id === user.defaultCalendarId;
})[0] || this.mainService.calendars[0];
}
);

this.activatedRoute.queryParams.subscribe(({ date }: { date?: string }) => {
if (date) {
const parsedDate = new Date(`${date}-01 00:00:00`);
if (DateUtil.valid(parsedDate)) {
parsedDate.setDate(this.mainService.visibleDate.getDate());
this.mainService.visibleDate = parsedDate;
}
}
});
}

public onRangeChange({ dateFrom, dateTo }: { dateFrom: Date; dateTo: Date }): void {
this.mainService.calendarDateFrom = dateFrom;
this.mainService.calendarDateTo = dateTo;
this.mainService.refreshCalendar();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
import {
NbButtonModule,
NbDialogRef,
NbDialogService,
NbIconModule,
NbToastrService,
} from '@nebular/theme';
import { CalendarApiService } from '../../../../../api/calendar.api.service';
import { Calendar } from '../../../../../api/objects/calendar';
import { User } from '../../../../../api/objects/user';
import { CalendarEditComponent } from '../../../dialogs/calendars-dialog/calendar-edit/calendar-edit.component';
import { ConfirmDialogComponent } from '../../../dialogs/confirm-dialog/confirm-dialog.component';

@Component({
selector: 'app-sidebar-calendar-list-actions',
template: `
<div class="d-flex justify-content-between">
<button nbButton fullWidth status="primary" ghost (click)="createCalendar()" class="pl-4" i18n>
<nb-icon icon="plus"></nb-icon>
Add a calendar...
</button>
</div>
`,
imports: [NbButtonModule, NbIconModule],
})
export class CalendarListActionsComponent {
@Input({ required: true }) public user: User;

@Output() public calendarsChange = new EventEmitter<Calendar[]>();

private readonly dialogService = inject(NbDialogService);
private readonly calendarApiService = inject(CalendarApiService);
private readonly toastrService = inject(NbToastrService);

private dialogRef: NbDialogRef<CalendarEditComponent>;
private readonly dialogBack = new EventEmitter<boolean>();
private readonly dialogSave = new EventEmitter<Calendar>();

public constructor() {
this.dialogBack.subscribe(() => this.dialogRef.close());
this.dialogSave.subscribe((calendar: Calendar) => {
this.calendarApiService.save(calendar).subscribe((saved: Calendar) => {
this.toastrService.success('Calendar saved successfully', 'Calendar update');
this.dialogRef.close(saved);
});
});
}

public createCalendar(): void {
this.openCalendarDialog(Calendar.create(this.user));
}

public editCalendar(calendar: Calendar): void {
this.calendarApiService.get(calendar.id).subscribe((cal: Calendar) => this.openCalendarDialog(cal));
}

public deleteCalendar(calendar: Calendar): void {
this.dialogService
.open(ConfirmDialogComponent, {
autoFocus: true,
context: {
question: 'Are you sure you want to delete calendar?',
},
})
.onClose.subscribe((result?: boolean) => {
if (result) {
this.calendarApiService.delete(calendar.id).subscribe(() => {
this.toastrService.success('Calendar deleted successfully', 'Calendar delete');
this.fetchCalendars();
});
}
});
}

private fetchCalendars(): void {
this.calendarApiService.list().subscribe((calendars: Calendar[]) => {
this.calendarsChange.emit(calendars);
});
}

private openCalendarDialog(calendar: Calendar): void {
this.dialogRef = this.dialogService.open(CalendarEditComponent, {
context: {
calendar,
back: this.dialogBack,
save: this.dialogSave,
},
});

this.dialogRef.onClose.subscribe((cal: Calendar) => {
if (cal !== undefined) {
this.fetchCalendars();
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<nb-list class="mb-3">
@for (cal of calendars; track $index) {
<nb-list-item class="p-0">
<nb-radio-group name="sidebar-calendar" class="w-100">
<nb-radio
class="ms-2"
[value]="cal"
(valueChange)="calendarSelect.emit($event)"
[checked]="cal?.id === calendar?.id">
<div class="d-flex align-items-center justify-content-between w-100">
<div class="calendar-name text-truncate">
@if (cal.shared) {
<nb-icon
[icon]="cal.isOwner(user) ? 'people' : 'people-outline'"
[title]="
cal.isOwner(user)
? 'Owned by me & shared with others'
: 'Shared with me by ' +
cal.owner.name +
' (' +
cal.owner.email +
')'
"
class="me-1 text-hint"></nb-icon>
} @else {
<nb-icon icon="person-outline" class="me-1 text-hint" title="Owned by me"></nb-icon>
}

{{ cal.name }}
</div>
<div class="calendar-balance text-hint">
{{ cal.balance | shortNumber }}
</div>
<div class="calendar-actions text-right">
<button
nbButton
ghost
size="small"
status="danger"
(click)="makeDefault.emit(cal)"
title="Make default">
<nb-icon icon="heart-outline"></nb-icon>
</button>

@if (cal.isOwner(user)) {
<button
nbButton
ghost
size="small"
status="primary"
(click)="editCalendar.emit(cal)"
title="Edit calendar">
<nb-icon icon="edit-outline"></nb-icon>
</button>
<button
nbButton
ghost
size="small"
status="danger"
(click)="deleteCalendar.emit(cal)"
title="Delete calendar">
<nb-icon icon="trash-2-outline"></nb-icon>
</button>
}
</div>
</div>
</nb-radio>
</nb-radio-group>
</nb-list-item>
}
</nb-list>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { NbButtonModule, NbIconModule, NbListModule, NbRadioModule } from '@nebular/theme';
import { Calendar } from '../../../../../api/objects/calendar';
import { User } from '../../../../../api/objects/user';
import { ShortNumberPipe } from '../../../../../pipes/shortnumber.pipe';

@Component({
selector: 'app-sidebar-calendar-list-display',
templateUrl: 'calendar-list-display.component.html',
styleUrls: ['calendar-list-display.component.scss'],
imports: [NbListModule, NbRadioModule, NbIconModule, NbButtonModule, ShortNumberPipe],
})
export class CalendarListDisplayComponent {
@Input({ required: true }) public calendars: Calendar[];
@Input({ required: true }) public calendar: Calendar;
@Input({ required: true }) public user: User;

@Output() public calendarSelect = new EventEmitter<Calendar>();
@Output() public makeDefault = new EventEmitter<Calendar>();
@Output() public editCalendar = new EventEmitter<Calendar>();
@Output() public deleteCalendar = new EventEmitter<Calendar>();
}

This file was deleted.

Loading
Loading