mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-08 14:32:50 +00:00
refactor: display of opening hours
This commit is contained in:
@@ -13,8 +13,8 @@
|
|||||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
<ion-card>
|
<ion-card>
|
||||||
<ion-card-content>
|
<ion-card-header>
|
||||||
<ion-text color="dark">
|
<ion-card-title>
|
||||||
<h1>
|
<h1>
|
||||||
<ng-container *ngIf="$any(item).honorificPrefix">{{
|
<ng-container *ngIf="$any(item).honorificPrefix">{{
|
||||||
'honorificPrefix' | thingTranslate: item
|
'honorificPrefix' | thingTranslate: item
|
||||||
@@ -24,9 +24,15 @@
|
|||||||
'honorificSuffix' | thingTranslate: item
|
'honorificSuffix' | thingTranslate: item
|
||||||
}}</ng-container>
|
}}</ng-container>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-text>
|
</ion-card-title>
|
||||||
|
</ion-card-header>
|
||||||
|
<ion-card-content>
|
||||||
|
<div *ngIf="$any(item).openingHours" class="openingHours">
|
||||||
|
<stapps-opening-hours
|
||||||
|
[openingHours]="item.openingHours"
|
||||||
|
></stapps-opening-hours>
|
||||||
|
</div>
|
||||||
<div *ngIf="item.description" class="description">
|
<div *ngIf="item.description" class="description">
|
||||||
<br />
|
|
||||||
<div
|
<div
|
||||||
class="text-accordion"
|
class="text-accordion"
|
||||||
[style.-webkit-line-clamp]="descriptionLinesToDisplay"
|
[style.-webkit-line-clamp]="descriptionLinesToDisplay"
|
||||||
|
|||||||
@@ -26,15 +26,24 @@ ion-card {
|
|||||||
--background: var(--ion-color-primary);
|
--background: var(--ion-color-primary);
|
||||||
padding: 0 var(--spacing-md);
|
padding: 0 var(--spacing-md);
|
||||||
|
|
||||||
ion-card-content {
|
ion-card-header {
|
||||||
padding: var(--spacing-sm) 0 var(--header-spacing-bottom);
|
padding: 0;
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: var(--ion-color-primary-contrast);
|
color: var(--ion-color-primary-contrast);
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
|
margin: var(--spacing-sm) 0 var(--spacing-sm) 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-card-content {
|
||||||
|
padding: 0 0 var(--header-spacing-bottom);
|
||||||
|
|
||||||
.description * {
|
.description * {
|
||||||
color: var(--ion-color-light);
|
color: var(--ion-color-light);
|
||||||
}
|
}
|
||||||
|
.openingHours {
|
||||||
|
color: var(--ion-color-light);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,11 @@
|
|||||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||||
<ng-container *ngIf="item.type !== 'floor'">
|
<ng-container *ngIf="item.type !== 'floor'">
|
||||||
<p class="title-sub" *ngIf="item.openingHours">
|
<p class="title-sub" *ngIf="item.openingHours">
|
||||||
{{ item.openingHours | openingHours }}
|
<span>
|
||||||
|
<stapps-opening-hours
|
||||||
|
[openingHours]="item.openingHours"
|
||||||
|
></stapps-opening-hours>
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<ion-note
|
<ion-note
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
|||||||
|
|
||||||
onLangChange?: Subscription;
|
onLangChange?: Subscription;
|
||||||
|
|
||||||
value = '';
|
value: string[] = [];
|
||||||
|
|
||||||
constructor(private readonly translate: TranslateService) {
|
constructor(private readonly translate: TranslateService) {
|
||||||
this.locale = translate.currentLang;
|
this.locale = translate.currentLang;
|
||||||
@@ -142,7 +142,7 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
|||||||
this._dispose();
|
this._dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
transform(aString: string | unknown): string {
|
transform(aString: string | unknown): string[] {
|
||||||
this.updateValue(aString);
|
this.updateValue(aString);
|
||||||
this._dispose();
|
this._dispose();
|
||||||
if (this.onLangChange?.closed === true) {
|
if (this.onLangChange?.closed === true) {
|
||||||
@@ -176,29 +176,87 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn(error);
|
logger.warn(error);
|
||||||
this.value = '';
|
this.value = [];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOpen: boolean = openingHours.getState();
|
const isOpen: boolean = openingHours.getState();
|
||||||
const nextChange: Date = openingHours.getNextChange();
|
const isUnknown: boolean = openingHours.getUnknown();
|
||||||
|
|
||||||
let prefixKey = isOpen
|
const nextChange: Date = openingHours.getNextChange();
|
||||||
? 'common.openingHours.open_until'
|
const nextChangeIsOpen: boolean = openingHours.getState(nextChange);
|
||||||
: 'common.openingHours.closed_until';
|
const nextChangeUnknown: boolean = openingHours.getUnknown(nextChange);
|
||||||
|
const nextChangeIsToday: boolean = moment().isSame(nextChange, 'day');
|
||||||
|
|
||||||
|
let stateKey = isOpen
|
||||||
|
? 'common.openingHours.state_open'
|
||||||
|
: 'common.openingHours.state_closed';
|
||||||
|
|
||||||
|
stateKey = isUnknown ? 'common.openingHours.state_maybe' : stateKey;
|
||||||
|
|
||||||
|
this.value = [
|
||||||
|
isOpen ? 'success' : 'danger',
|
||||||
|
`${this.translate.instant(stateKey)}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isUnknown) {
|
||||||
|
const comment = openingHours.getComment();
|
||||||
|
this.value = ['light', `${this.translate.instant(stateKey)}`];
|
||||||
|
if (typeof comment === 'string') {
|
||||||
|
this.value.push(comment);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextChangeUnknown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextChangeKey: string | undefined;
|
||||||
|
|
||||||
let formattedCalender = moment(nextChange).calendar();
|
let formattedCalender = moment(nextChange).calendar();
|
||||||
|
|
||||||
if (moment(nextChange).isBefore(moment().add(1, 'hours'))) {
|
if (moment(nextChange).isBefore(moment().add(1, 'hours'))) {
|
||||||
prefixKey = isOpen
|
this.value[0] = 'warning';
|
||||||
? 'common.openingHours.closing_soon'
|
nextChangeKey = nextChangeIsOpen
|
||||||
: 'common.openingHours.opening_soon';
|
? 'common.openingHours.opening_soon_warning'
|
||||||
formattedCalender =
|
: 'common.openingHours.closing_soon_warning';
|
||||||
formattedCalender.slice(0, 1).toUpperCase() +
|
this.value.push(
|
||||||
formattedCalender.slice(1);
|
`${this.translate.instant(nextChangeKey, {
|
||||||
|
time: new Intl.DateTimeFormat(this.locale, {
|
||||||
|
timeStyle: 'short',
|
||||||
|
}).format(nextChange),
|
||||||
|
})}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.value = `${this.translate.instant(prefixKey)} ${formattedCalender}`;
|
|
||||||
|
if (nextChangeIsToday) {
|
||||||
|
nextChangeKey = nextChangeIsOpen
|
||||||
|
? 'common.openingHours.opening_today'
|
||||||
|
: 'common.openingHours.closing_today';
|
||||||
|
this.value.push(
|
||||||
|
`${this.translate.instant(nextChangeKey, {
|
||||||
|
time: new Intl.DateTimeFormat(this.locale, {
|
||||||
|
timeStyle: 'short',
|
||||||
|
}).format(nextChange),
|
||||||
|
})}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextChangeKey = nextChangeIsOpen
|
||||||
|
? 'common.openingHours.opening'
|
||||||
|
: 'common.openingHours.closing';
|
||||||
|
formattedCalender =
|
||||||
|
formattedCalender.slice(0, 1).toUpperCase() + formattedCalender.slice(1);
|
||||||
|
this.value.push(
|
||||||
|
`${this.translate.instant(nextChangeKey, {
|
||||||
|
relativeDateTime: formattedCalender,
|
||||||
|
})}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
30
src/app/util/opening-hours.component.ts
Normal file
30
src/app/util/opening-hours.component.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Component, ContentChild, Input, TemplateRef} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'stapps-opening-hours',
|
||||||
|
templateUrl: 'opening-hours.html',
|
||||||
|
})
|
||||||
|
export class OpeningHoursComponent {
|
||||||
|
@ContentChild(TemplateRef) content: TemplateRef<unknown>;
|
||||||
|
|
||||||
|
@Input() openingHours?: string;
|
||||||
|
|
||||||
|
@Input() colorize = true;
|
||||||
|
|
||||||
|
@Input() showNextChange = true;
|
||||||
|
}
|
||||||
34
src/app/util/opening-hours.html
Normal file
34
src/app/util/opening-hours.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 StApps
|
||||||
|
~ This program is free software: you can redistribute it and/or modify it
|
||||||
|
~ under the terms of the GNU General Public License as published by the Free
|
||||||
|
~ Software Foundation, version 3.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
~ more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License along with
|
||||||
|
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ng-container *ngIf="openingHours">
|
||||||
|
<div>
|
||||||
|
<ng-template [ngIf]="colorize" [ngIfElse]="blank">
|
||||||
|
<ion-badge
|
||||||
|
[color]="openingHours | openingHours | slice: 0:1 | join: ' '"
|
||||||
|
slot="start"
|
||||||
|
style="vertical-align: bottom"
|
||||||
|
>
|
||||||
|
{{ openingHours | openingHours | slice: 1:2 }}
|
||||||
|
</ion-badge>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #blank>
|
||||||
|
{{ openingHours | openingHours | slice: 1:2 }}
|
||||||
|
</ng-template>
|
||||||
|
<ng-container *ngIf="showNextChange">
|
||||||
|
{{ openingHours | openingHours | slice: 2:3 }}
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
@@ -25,9 +25,16 @@ import {BrowserModule} from '@angular/platform-browser';
|
|||||||
import {IonicModule} from '@ionic/angular';
|
import {IonicModule} from '@ionic/angular';
|
||||||
import {TranslateModule} from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
import {ElementSizeChangeDirective} from './element-size-change.directive';
|
import {ElementSizeChangeDirective} from './element-size-change.directive';
|
||||||
|
import {OpeningHoursComponent} from './opening-hours.component';
|
||||||
|
import {ThingTranslateModule} from '../translation/thing-translate.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [BrowserModule, IonicModule, TranslateModule],
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
IonicModule,
|
||||||
|
TranslateModule,
|
||||||
|
ThingTranslateModule.forChild(),
|
||||||
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
ElementSizeChangeDirective,
|
ElementSizeChangeDirective,
|
||||||
ArrayLastPipe,
|
ArrayLastPipe,
|
||||||
@@ -38,6 +45,7 @@ import {ElementSizeChangeDirective} from './element-size-change.directive';
|
|||||||
DaytimeKeyPipe,
|
DaytimeKeyPipe,
|
||||||
NextDateInListPipe,
|
NextDateInListPipe,
|
||||||
EditModalComponent,
|
EditModalComponent,
|
||||||
|
OpeningHoursComponent,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
ElementSizeChangeDirective,
|
ElementSizeChangeDirective,
|
||||||
@@ -49,6 +57,7 @@ import {ElementSizeChangeDirective} from './element-size-change.directive';
|
|||||||
DaytimeKeyPipe,
|
DaytimeKeyPipe,
|
||||||
NextDateInListPipe,
|
NextDateInListPipe,
|
||||||
EditModalComponent,
|
EditModalComponent,
|
||||||
|
OpeningHoursComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class UtilModule {}
|
export class UtilModule {}
|
||||||
|
|||||||
@@ -54,10 +54,15 @@
|
|||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"openingHours": {
|
"openingHours": {
|
||||||
"closed_until": "Geschlossen bis",
|
"closing": "Schließt {{relativeDateTime}}",
|
||||||
"closing_soon": "Schließt bald!",
|
"closing_soon_warning": "Schließt bald! Um {{time}} Uhr",
|
||||||
"open_until": "Geöffnet bis",
|
"closing_today": "Schließt um {{time}} Uhr",
|
||||||
"opening_soon": "Öffnet"
|
"state_closed": "Geschlossen",
|
||||||
|
"state_maybe": "Vielleicht Geöffnet",
|
||||||
|
"state_open": "Geöffnet",
|
||||||
|
"opening": "Öffnet {{relativeDateTime}}",
|
||||||
|
"opening_today": "Öffnet um {{time}} Uhr",
|
||||||
|
"opening_soon_warning": "Öffnet bald! Um {{time}} Uhr"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
|
|||||||
@@ -54,10 +54,15 @@
|
|||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"openingHours": {
|
"openingHours": {
|
||||||
"closed_until": "Closed until",
|
"closing": "Closing {{relativeDateTime}}",
|
||||||
"closing_soon": "Closing soon!",
|
"closing_soon_warning": "Closing soon! At {{time}}",
|
||||||
"open_until": "Open until",
|
"closing_today": "Closing at {{time}}",
|
||||||
"opening_soon": "Opens"
|
"state_closed": "Closed",
|
||||||
|
"state_maybe": "Maybe open",
|
||||||
|
"state_open": "Open",
|
||||||
|
"opening": "Opens {{relativeDateTime}}",
|
||||||
|
"opening_today": "Opens at {{time}}",
|
||||||
|
"opening_soon_warning": "Opens soon! At {{time}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
body app-root {
|
body app-root {
|
||||||
.title,
|
.title,
|
||||||
.title-sub,
|
.title[class*='sc-ion-label'] {
|
||||||
.title[class*='sc-ion-label'],
|
|
||||||
.title-sub[class*='sc-ion-label'] {
|
|
||||||
font-size: var(--font-size-md);
|
font-size: var(--font-size-md);
|
||||||
font-weight: var(--font-weight-semi-bold);
|
font-weight: var(--font-weight-semi-bold);
|
||||||
// TODO Condensed Font
|
// TODO Condensed Font
|
||||||
}
|
}
|
||||||
|
.title-sub,
|
||||||
|
.title-sub[class*='sc-ion-label'] {
|
||||||
|
font-size: var(--font-size-md);
|
||||||
|
font-weight: var(--font-weight-regular);
|
||||||
|
// TODO Condensed Font
|
||||||
|
}
|
||||||
|
|
||||||
.title-sub {
|
.title-sub {
|
||||||
color: var(--ion-color-primary);
|
color: var(--ion-color-text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user