Skip to content

Commit

Permalink
added summary page
Browse files Browse the repository at this point in the history
  • Loading branch information
ortwic committed Apr 5, 2024
1 parent e8411a5 commit cbacbce
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 31 deletions.
6 changes: 6 additions & 0 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { SettingsComponent } from './pages/settings/settings.component';
import { ImprintComponent } from './pages/imprint/imprint.component';
import { PrivacyComponent } from './pages/privacy/privacy.component';
import { ErrorComponent } from './pages/error/error.component';
import { SummaryComponent } from './pages/summary/summary.component';

export const routes: Routes = [
{
Expand All @@ -22,6 +23,11 @@ export const routes: Routes = [
page: (route: ActivatedRouteSnapshot) => route.params['page']
}
},
{
path: 'summary',
title: 'Auswertung | Why App',
component: SummaryComponent,
},
{
path: 'blog',
title: 'Blog | Why App',
Expand Down
15 changes: 15 additions & 0 deletions src/app/models/result.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { InputValue } from "./content.model";

export type ResultValue = Result | Progress | Record<string, InputValue> | undefined;

export interface Result {
[key: string]: ResultValue;
data?: Record<string, InputValue>;
progress: Progress;
}

export interface Progress {
count: number;
total: number;
percent: number;
}
2 changes: 1 addition & 1 deletion src/app/pages/page/page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class PageComponent {
completed: true,
data: {
...data,
[pageReadTime]: elapsedTime
[pageReadTime]: elapsedTime / 1000
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/start/start.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ <h3>
</mat-card-content>
<mat-card-footer class="footer">
@if (pageProgressPercent($index, section.slug) > 99) {
<mat-icon fontIcon="check_box"/> Erledigt
<mat-icon fontIcon="task_alt"/> Erledigt
} @else {
<mat-icon fontIcon="check_box_outline_blank"/> Offen
<mat-icon fontIcon="radio_button_unchecked"/> Offen
}
</mat-card-footer>
</mat-card>
Expand Down
8 changes: 4 additions & 4 deletions src/app/pages/start/start.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
header {
margin-bottom: 4rem;
margin-bottom: 4rem;

[mat-subheader] {
color: var(--mat-card-subtitle-text-color);;
Expand Down Expand Up @@ -76,7 +76,7 @@ small {

.card {
flex: 1 0 auto;
max-width: 400px;
max-width: 367px;

.card-header {
display: flex;
Expand All @@ -95,9 +95,9 @@ small {
.card-content {
padding: 0;

img {
.thumbnail {
width: 100%;
height: 200px;
max-height: 200px;
object-fit: cover;
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/app/pages/start/start.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { LoadingComponent } from '../../components/ui/loading/loading.component'
import { ProgressSpinnerComponent } from '../../components/ui/progress-spinner/progress-spinner.component';
import { CommonService } from '../../services/common.service';
import { GuideService } from '../../services/guide.service';
import { Progress, UserProgressService } from '../../services/user-progress.service';
import { UserResultService } from '../../services/user-result.service';
import { Guide } from '../../models/guide.model';
import { Result } from '../../models/result.model';

@Component({
selector: 'app-start',
Expand All @@ -29,18 +30,18 @@ import { Guide } from '../../models/guide.model';
export class StartComponent {
private readonly _commonService = inject(CommonService);
private readonly _guideService = inject(GuideService);
private readonly _progressService = inject(UserProgressService);
private readonly _resultService = inject(UserResultService);

private _resources: Record<string, unknown> = {};
private _units!: Guide[];
private _progress!: Progress[];
private _results!: Result[];
private _greeting!: string;
private _userName!: string;
loading = true;

async ngOnInit() {
this._units = await this._guideService.dataPromise;
this._progress = await this._progressService.progressTree;
this._results = await this._resultService.resultTree;

this._resources = await this._commonService.getResources('start');
this.setUserName(this._resources['user-names'] as string[]);
Expand Down Expand Up @@ -87,10 +88,10 @@ export class StartComponent {
}

unitProgressPercent(unitIndex: number) {
return this._progress ? this._progress[unitIndex].percent : 0;
return this._results ? this._results[unitIndex].progress.percent : 0;
}

pageProgressPercent(unitIndex: number, pageId: string) {
return this._progress ? (<Progress>this._progress[unitIndex][pageId]).percent : 0;
return this._results ? (<Result>this._results[unitIndex][pageId]).progress.percent : 0;
}
}
47 changes: 47 additions & 0 deletions src/app/pages/summary/summary.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<app-loading [loading]="loading">
@for (unit of summary; track $index) {
<div class="header">
<h2>
{{resource('unit')}} {{$index + 1}}
</h2>
<span class="sub">{{title($index)}}</span>
<app-progress-spinner [size]="40" [value]="unit.progress.percent">
<small>{{unit.progress.percent}}%</small>
</app-progress-spinner>
</div>
<mat-accordion multi>
<ng-container *ngFor="let page of pages($index) | async">
@if (data(unit[page.slug])) {
<mat-expansion-panel expanded>
<mat-expansion-panel-header>
<mat-panel-title class="header">
<span>{{page.title}}</span>
<small>{{percent(unit[page.slug])}}%</small>
</mat-panel-title>
</mat-expansion-panel-header>
<div class="content">
@for (item of data(unit[page.slug]) | keyvalue: doneAtLast; track $index) {
@if (item.key === doneKey) {
<mat-divider /><br/>
<label [title]="item.value + 's'">
<mat-icon fontIcon="task_alt"/> Erledigt
</label>
} @else {
<label>
{{caption(page, item.key)}}
</label>
<div class="value">
{{format(item.value) || 'Keine Angabe'}}
</div>
}
}
</div>
</mat-expansion-panel>
}
</ng-container>
</mat-accordion>
<mat-divider class="spacer" />
}

<app-settings />
</app-loading>
42 changes: 42 additions & 0 deletions src/app/pages/summary/summary.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;

h2 {
font-size: large;
letter-spacing: .1rem;
}

.sub {
font-size: large;
font-weight: normal;
}

small {
font-size: 8pt;
}
}

.content {
padding: 1rem;
line-height: 1.5;

label {
display: flex;
align-items: center;
gap: .4rem;
color: var(--primary);
font-weight: 500;
}

.value {
padding: 1rem;
font-weight: 100;
}
}

.spacer {
margin-bottom: 4rem;
}
23 changes: 23 additions & 0 deletions src/app/pages/summary/summary.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { SummaryComponent } from './summary.component';

describe('SummaryComponent', () => {
let component: SummaryComponent;
let fixture: ComponentFixture<SummaryComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SummaryComponent]
})
.compileComponents();

fixture = TestBed.createComponent(SummaryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
100 changes: 100 additions & 0 deletions src/app/pages/summary/summary.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Component, inject } from '@angular/core';
import { CommonModule, KeyValue } from '@angular/common';
import { MatAccordion, MatExpansionModule } from '@angular/material/expansion';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { SettingsComponent } from '../settings/settings.component';
import { LoadingComponent } from '../../components/ui/loading/loading.component';
import { ProgressSpinnerComponent } from '../../components/ui/progress-spinner/progress-spinner.component';
import { GuideService } from '../../services/guide.service';
import { Guide } from '../../models/guide.model';
import { Result, ResultValue } from '../../models/result.model';
import { InputDefinition, InputValue } from '../../models/content.model';
import { Page } from '../../models/page.model';
import { CommonService } from '../../services/common.service';
import { UserResultService } from '../../services/user-result.service';
import { pageReadTime } from '../../services/user-data.service';

@Component({
selector: 'app-summary',
standalone: true,
imports: [
CommonModule,
MatAccordion,
MatExpansionModule,
MatDividerModule,
MatIconModule,
LoadingComponent,
ProgressSpinnerComponent,
SettingsComponent
],
templateUrl: './summary.component.html',
styleUrl: './summary.component.scss',
})
export class SummaryComponent {
private readonly _commonService = inject(CommonService);
private readonly _guideService = inject(GuideService);
private readonly _resultService = inject(UserResultService);

private _resources: Record<string, unknown> = {};
private _units!: Guide[];
private _results!: Result[];
readonly doneKey = pageReadTime;
loading = true;

async ngOnInit() {
this._units = await this._guideService.dataPromise;
this._results = await this._resultService.resultTree;
this._resources = await this._commonService.getResources('start');

this.loading = false;
}

get summary() {
return this._results;
}

resource(key: string) {
return this._resources[key];
}

title(index: number) {
return this._units[index].title;
}

pages(index: number) {
return this._units[index].pages;
}

data(result: ResultValue) {
const data = (<Result>result).data;
if (data && data[this.doneKey]) {
return Object.keys(data).reduce((acc, key) => {
acc[key] = data[key];
return acc;
}, {} as Record<string, InputValue>);
}
return null;
}

percent(result: ResultValue) {
return (<Result>result).progress.percent;
}

caption(page: Page, id: string) {
return page.content
.filter(item => item.type === 'stepper')
.flatMap(item => item.value as InputDefinition[])
.find(item => item.value.id === id)?.value?.caption || id;
}

format(value: InputValue) {
return Array.isArray(value)
? value.join(', ')
: value;
}

doneAtLast(a: KeyValue<string, InputValue>) {
return a.key.startsWith('__') ? 1 : -1;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { TestBed } from '@angular/core/testing';

import { UserProgressService } from './user-progress.service';
import { UserResultService } from './user-result.service';

xdescribe('UserProgressService', () => {
let service: UserProgressService;
xdescribe('UserResultService', () => {
let service: UserResultService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserProgressService);
service = TestBed.inject(UserResultService);
});

it('should be created', () => {
Expand Down
Loading

0 comments on commit cbacbce

Please sign in to comment.