fix: Remade menu editor loading logic
This commit is contained in:
@@ -43,7 +43,7 @@ export class AccountMgmtComponent implements AfterViewInit {
|
||||
}
|
||||
this.ac.refresh()
|
||||
this.ac.accs.subscribe(d => {
|
||||
this.users.data = d ?? []
|
||||
this.users.data = d
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +1,110 @@
|
||||
<div id="upper-bar">
|
||||
<mat-form-field>
|
||||
<mat-form-field subscriptSizing="dynamic">
|
||||
<mat-label>Wybierz tydzień</mat-label>
|
||||
<mat-date-range-input [rangePicker]="picker" [formGroup]="range">
|
||||
<input matStartDate formControlName="start" (dateChange)="requestData()">
|
||||
<input matEndDate formControlName="end" (dateChange)="requestData()">
|
||||
<input matStartDate formControlName="start">
|
||||
<input matEndDate formControlName="end">
|
||||
</mat-date-range-input>
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-date-range-picker #picker></mat-date-range-picker>
|
||||
</mat-form-field>
|
||||
<button mat-icon-button (click)="requestData()"><mat-icon>refresh</mat-icon></button>
|
||||
<button mat-icon-button (click)="ac.refresh()"><mat-icon>search</mat-icon></button>
|
||||
<button mat-icon-button (click)="addDate()"><mat-icon>add</mat-icon></button>
|
||||
<button mat-icon-button (click)="print()"><mat-icon>print</mat-icon></button>
|
||||
</div>
|
||||
@if (loading) {
|
||||
<mat-spinner></mat-spinner>
|
||||
}
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<div matColumnDef="day">
|
||||
<th mat-header-cell *matHeaderCellDef>Dzień</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<span>{{element.day.toFormat('dd.LL.yyyy')}}r.</span>
|
||||
<p>{{element.day.toFormat('cccc') | titlecase }}</p>
|
||||
<app-field-editor category="Nazwa" [(word)]="element.dayTitle" (wordChange)="editTitle(element._id)"/><br><hr>
|
||||
<button (click)="remove(element._id)">Usuń dzień</button>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="sn">
|
||||
<th mat-header-cell *matHeaderCellDef>Śniadanie</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<ul class="non-editable">
|
||||
@for (i of ls.defaultItems.sn; track i) {
|
||||
<li>{{i}}</li>
|
||||
}
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.sn.fancy" (edit)="editSn(element._id)" dataList="sn-fancy"/><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="II Śniadanie" [(word)]="element.sn.second" list="sn-second" (wordChange)="editSn(element._id)"/></li>
|
||||
</ul>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="ob">
|
||||
<th mat-header-cell *matHeaderCellDef>Obiad</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<ul>
|
||||
<li><app-field-editor category="Zupa" [(word)]="element.ob.soup" list="ob-soup" (wordChange)="editOb(element._id)"/></li>
|
||||
<li><app-field-editor category="Vege" [(word)]="element.ob.vege" list="ob-vege" (wordChange)="editOb(element._id)"/></li>
|
||||
<li><app-field-editor category="Danie główne" [(word)]="element.ob.meal" list="ob-meal" (wordChange)="editOb(element._id)"/></li>
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.ob.condiments" (edit)="editOb(element._id)" dataList="ob-condiments"/><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="Napój" [(word)]="element.ob.drink" list="ob-drink" (wordChange)="editOb(element._id)"/></li>
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.ob.other" (edit)="editOb(element._id)" dataList="ob-other"/>
|
||||
<button (click)="getStat(element.day, 'ob')">
|
||||
Opinie wychowanków
|
||||
</button>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="kol">
|
||||
<th mat-header-cell *matHeaderCellDef>Kolacja</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div>
|
||||
@switch (element.day.weekday) {
|
||||
@default {
|
||||
<div>
|
||||
<ul class="non-editable">
|
||||
@for (i of ls.defaultItems.kol; track i) {
|
||||
<li>{{i}}</li>
|
||||
}
|
||||
</ul><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="Kolacja" [(word)]="element.kol" list="kol" (wordChange)="editKol(element._id)"/></li>
|
||||
</ul>
|
||||
<button (click)="getStat(element.day, 'kol')">
|
||||
Opinie wychowanków
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@case (5) {
|
||||
<div class="non-editable">
|
||||
<p>Kolacja w domu!</p>
|
||||
<p>(Nie edytowalne)</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="mainc">
|
||||
@switch (ac.state()) {
|
||||
@case (0) {
|
||||
<p>Wybierz zakres dat powyżej i kliknij szukaj</p>
|
||||
}
|
||||
@case (1) {
|
||||
<div class="spinner">
|
||||
<mat-spinner/>
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
}
|
||||
@case (2) {
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<div matColumnDef="day">
|
||||
<th mat-header-cell *matHeaderCellDef>Dzień</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<span>{{element.day.toFormat('dd.LL.yyyy')}}r.</span>
|
||||
<p>{{element.day.toFormat('cccc') | titlecase }}</p>
|
||||
<app-field-editor category="Nazwa" [(word)]="element.dayTitle" (wordChange)="editTitle(element._id)"/><br><hr>
|
||||
<button (click)="remove(element._id)">Usuń dzień</button>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="sn">
|
||||
<th mat-header-cell *matHeaderCellDef>Śniadanie</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<ul class="non-editable">
|
||||
@for (i of ls.defaultItems.sn; track i) {
|
||||
<li>{{i}}</li>
|
||||
}
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.sn.fancy" (edit)="editSn(element._id)" dataList="sn-fancy"/><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="II Śniadanie" [(word)]="element.sn.second" list="sn-second" (wordChange)="editSn(element._id)"/></li>
|
||||
</ul>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="ob">
|
||||
<th mat-header-cell *matHeaderCellDef>Obiad</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<ul>
|
||||
<li><app-field-editor category="Zupa" [(word)]="element.ob.soup" list="ob-soup" (wordChange)="editOb(element._id)"/></li>
|
||||
<li><app-field-editor category="Vege" [(word)]="element.ob.vege" list="ob-vege" (wordChange)="editOb(element._id)"/></li>
|
||||
<li><app-field-editor category="Danie główne" [(word)]="element.ob.meal" list="ob-meal" (wordChange)="editOb(element._id)"/></li>
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.ob.condiments" (edit)="editOb(element._id)" dataList="ob-condiments"/><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="Napój" [(word)]="element.ob.drink" list="ob-drink" (wordChange)="editOb(element._id)"/></li>
|
||||
</ul><hr>
|
||||
<app-list-editor [(list)]="element.ob.other" (edit)="editOb(element._id)" dataList="ob-other"/>
|
||||
<button (click)="getStat(element.day, 'ob')">
|
||||
Opinie wychowanków
|
||||
</button>
|
||||
</td>
|
||||
</div>
|
||||
<div matColumnDef="kol">
|
||||
<th mat-header-cell *matHeaderCellDef>Kolacja</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div>
|
||||
@switch (element.day.weekday) {
|
||||
@default {
|
||||
<div>
|
||||
<ul class="non-editable">
|
||||
@for (i of ls.defaultItems.kol; track i) {
|
||||
<li>{{i}}</li>
|
||||
}
|
||||
</ul><hr>
|
||||
<ul>
|
||||
<li><app-field-editor category="Kolacja" [(word)]="element.kol" list="kol" (wordChange)="editKol(element._id)"/></li>
|
||||
</ul>
|
||||
<button (click)="getStat(element.day, 'kol')">
|
||||
Opinie wychowanków
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@case (5) {
|
||||
<div class="non-editable">
|
||||
<p>Kolacja w domu!</p>
|
||||
<p>(Nie edytowalne)</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="dcols"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: dcols"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="dcols"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: dcols"></tr>
|
||||
</table>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (options) {
|
||||
<datalist id="sn-fancy">
|
||||
@@ -138,4 +152,4 @@
|
||||
<option>{{i}}</option>
|
||||
}
|
||||
</datalist>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,3 +16,19 @@ button[mat-icon-button] {
|
||||
color: gray;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.mainc {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@@ -33,11 +33,18 @@ export class MenuEditComponent {
|
||||
public options: any
|
||||
|
||||
constructor(
|
||||
private ac: MenuEditService,
|
||||
protected ac: MenuEditService,
|
||||
private dialog: MatDialog,
|
||||
private sb: MatSnackBar,
|
||||
readonly ls: LocalStorageService
|
||||
) {}
|
||||
) {
|
||||
this.range.valueChanges.subscribe(v => {
|
||||
ac.setDates(v.start!, v.end!)
|
||||
})
|
||||
ac.menuItems.subscribe(v => {
|
||||
this.dataSource.data = v
|
||||
})
|
||||
}
|
||||
|
||||
print() {
|
||||
this.ac
|
||||
@@ -74,7 +81,7 @@ export class MenuEditComponent {
|
||||
.subscribe(s => this.refreshIfGood(s))
|
||||
break
|
||||
case 'file':
|
||||
this.requestData()
|
||||
this.refresh()
|
||||
break
|
||||
default:
|
||||
break
|
||||
@@ -83,29 +90,15 @@ export class MenuEditComponent {
|
||||
})
|
||||
}
|
||||
|
||||
requestData() {
|
||||
this.loading = true
|
||||
refresh() {
|
||||
this.ac.refresh()
|
||||
this.ac.getOpts().subscribe(o => {
|
||||
this.options = o
|
||||
})
|
||||
this.ac
|
||||
.getMenu(this.range.value.start, this.range.value.end)
|
||||
?.subscribe(data => {
|
||||
this.loading = false
|
||||
this.dataSource.data = data.map(v => {
|
||||
let newMenu: Menu = {
|
||||
...v,
|
||||
day: DateTime.fromISO(v.day),
|
||||
}
|
||||
return newMenu
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private refreshIfGood(s: Status) {
|
||||
if (s.status.toString().match(/2\d\d/)) {
|
||||
this.requestData()
|
||||
}
|
||||
if (s.status.toString().match(/2\d\d/)) this.refresh()
|
||||
}
|
||||
|
||||
activateUpload() {
|
||||
@@ -113,9 +106,7 @@ export class MenuEditComponent {
|
||||
.open(MenuUploadComponent)
|
||||
.afterClosed()
|
||||
.subscribe(data => {
|
||||
if (data) {
|
||||
this.requestData()
|
||||
}
|
||||
if (data) this.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, signal } from '@angular/core';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Menu } from 'src/app/types/menu';
|
||||
import { BehaviorSubject, catchError, map, of } from 'rxjs';
|
||||
import { Menu, MenuAPI } from 'src/app/types/menu';
|
||||
import { STATE } from 'src/app/types/state';
|
||||
import { Status } from 'src/app/types/status';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@@ -10,19 +12,57 @@ import { environment } from 'src/environments/environment';
|
||||
})
|
||||
export class MenuEditService {
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
private _menuItems = new BehaviorSubject<Menu[]>([])
|
||||
public readonly menuItems = this._menuItems.asObservable()
|
||||
private _state = signal(STATE.NOT_LOADED);
|
||||
public readonly state = this._state.asReadonly();
|
||||
private _error = signal<string | undefined>(undefined);
|
||||
public readonly error = this._error.asReadonly();
|
||||
|
||||
getMenu(start?: DateTime | null, end?: DateTime | null) {
|
||||
if (start && end) {
|
||||
const body = { start: start.toString(), end: end.toString() }
|
||||
return this.http.get<(Omit<Menu, 'day'> & { day: string })[]>(
|
||||
environment.apiEndpoint + '/admin/menu',
|
||||
{ withCredentials: true, params: body }
|
||||
)
|
||||
private seDates: {
|
||||
start: DateTime | null,
|
||||
end: DateTime | null
|
||||
} = {
|
||||
start: null,
|
||||
end: null
|
||||
}
|
||||
return
|
||||
|
||||
public setDates(start: DateTime | null, end: DateTime | null) {
|
||||
this.seDates.start = start
|
||||
this.seDates.end = end
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
this.getMenu()
|
||||
}
|
||||
|
||||
private getMenu() {
|
||||
if (!(this.seDates.start && this.seDates.end)) return
|
||||
this._state.set(STATE.PENDING)
|
||||
const body = { start: this.seDates.start.toString(), end: this.seDates.end.toString() }
|
||||
this.http.get
|
||||
<MenuAPI[]>
|
||||
(environment.apiEndpoint + `/admin/menu`, { withCredentials: true, params: body })
|
||||
.pipe(
|
||||
catchError((err: Error) => {
|
||||
this._state.set(STATE.ERROR)
|
||||
this._error.set(err.message)
|
||||
return of()
|
||||
}),
|
||||
map<MenuAPI[], Menu[]>(v =>
|
||||
v.map(i => ({
|
||||
...i,
|
||||
day: DateTime.fromISO(i.day)
|
||||
})))
|
||||
).subscribe(v => {
|
||||
this._error.set(undefined)
|
||||
this._menuItems.next(v ?? [])
|
||||
this._state.set(STATE.LOADED)
|
||||
})
|
||||
}
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getOpts() {
|
||||
return this.http.get<any>(environment.apiEndpoint + `/admin/menu/opts`, {
|
||||
withCredentials: true,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { DateTime } from 'luxon'
|
||||
|
||||
export type MenuAPI = Omit<Menu, "day"> & {day: string}
|
||||
|
||||
export interface Menu {
|
||||
_id: string
|
||||
day: DateTime
|
||||
|
||||
Reference in New Issue
Block a user