mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2025-12-18 04:06:19 +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/>.
|
||||
-->
|
||||
<ion-card>
|
||||
<ion-card-content>
|
||||
<ion-text color="dark">
|
||||
<ion-card-header>
|
||||
<ion-card-title>
|
||||
<h1>
|
||||
<ng-container *ngIf="$any(item).honorificPrefix">{{
|
||||
'honorificPrefix' | thingTranslate: item
|
||||
@@ -24,9 +24,15 @@
|
||||
'honorificSuffix' | thingTranslate: item
|
||||
}}</ng-container>
|
||||
</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">
|
||||
<br />
|
||||
<div
|
||||
class="text-accordion"
|
||||
[style.-webkit-line-clamp]="descriptionLinesToDisplay"
|
||||
|
||||
@@ -26,15 +26,24 @@ ion-card {
|
||||
--background: var(--ion-color-primary);
|
||||
padding: 0 var(--spacing-md);
|
||||
|
||||
ion-card-content {
|
||||
padding: var(--spacing-sm) 0 var(--header-spacing-bottom);
|
||||
ion-card-header {
|
||||
padding: 0;
|
||||
|
||||
h1 {
|
||||
color: var(--ion-color-primary-contrast);
|
||||
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 * {
|
||||
color: var(--ion-color-light);
|
||||
}
|
||||
.openingHours {
|
||||
color: var(--ion-color-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<ng-container *ngIf="item.type !== 'floor'">
|
||||
<p class="title-sub" *ngIf="item.openingHours">
|
||||
{{ item.openingHours | openingHours }}
|
||||
<span>
|
||||
<stapps-opening-hours
|
||||
[openingHours]="item.openingHours"
|
||||
></stapps-opening-hours>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<ion-note
|
||||
|
||||
@@ -126,7 +126,7 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
||||
|
||||
onLangChange?: Subscription;
|
||||
|
||||
value = '';
|
||||
value: string[] = [];
|
||||
|
||||
constructor(private readonly translate: TranslateService) {
|
||||
this.locale = translate.currentLang;
|
||||
@@ -142,7 +142,7 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
||||
this._dispose();
|
||||
}
|
||||
|
||||
transform(aString: string | unknown): string {
|
||||
transform(aString: string | unknown): string[] {
|
||||
this.updateValue(aString);
|
||||
this._dispose();
|
||||
if (this.onLangChange?.closed === true) {
|
||||
@@ -176,29 +176,87 @@ export class OpeningHoursPipe implements PipeTransform, OnDestroy {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.warn(error);
|
||||
this.value = '';
|
||||
this.value = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const isOpen: boolean = openingHours.getState();
|
||||
const nextChange: Date = openingHours.getNextChange();
|
||||
const isUnknown: boolean = openingHours.getUnknown();
|
||||
|
||||
let prefixKey = isOpen
|
||||
? 'common.openingHours.open_until'
|
||||
: 'common.openingHours.closed_until';
|
||||
const nextChange: Date = openingHours.getNextChange();
|
||||
const nextChangeIsOpen: boolean = openingHours.getState(nextChange);
|
||||
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();
|
||||
|
||||
if (moment(nextChange).isBefore(moment().add(1, 'hours'))) {
|
||||
prefixKey = isOpen
|
||||
? 'common.openingHours.closing_soon'
|
||||
: 'common.openingHours.opening_soon';
|
||||
formattedCalender =
|
||||
formattedCalender.slice(0, 1).toUpperCase() +
|
||||
formattedCalender.slice(1);
|
||||
this.value[0] = 'warning';
|
||||
nextChangeKey = nextChangeIsOpen
|
||||
? 'common.openingHours.opening_soon_warning'
|
||||
: 'common.openingHours.closing_soon_warning';
|
||||
this.value.push(
|
||||
`${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 {TranslateModule} from '@ngx-translate/core';
|
||||
import {ElementSizeChangeDirective} from './element-size-change.directive';
|
||||
import {OpeningHoursComponent} from './opening-hours.component';
|
||||
import {ThingTranslateModule} from '../translation/thing-translate.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule, IonicModule, TranslateModule],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
IonicModule,
|
||||
TranslateModule,
|
||||
ThingTranslateModule.forChild(),
|
||||
],
|
||||
declarations: [
|
||||
ElementSizeChangeDirective,
|
||||
ArrayLastPipe,
|
||||
@@ -38,6 +45,7 @@ import {ElementSizeChangeDirective} from './element-size-change.directive';
|
||||
DaytimeKeyPipe,
|
||||
NextDateInListPipe,
|
||||
EditModalComponent,
|
||||
OpeningHoursComponent,
|
||||
],
|
||||
exports: [
|
||||
ElementSizeChangeDirective,
|
||||
@@ -49,6 +57,7 @@ import {ElementSizeChangeDirective} from './element-size-change.directive';
|
||||
DaytimeKeyPipe,
|
||||
NextDateInListPipe,
|
||||
EditModalComponent,
|
||||
OpeningHoursComponent,
|
||||
],
|
||||
})
|
||||
export class UtilModule {}
|
||||
|
||||
@@ -54,10 +54,15 @@
|
||||
},
|
||||
"common": {
|
||||
"openingHours": {
|
||||
"closed_until": "Geschlossen bis",
|
||||
"closing_soon": "Schließt bald!",
|
||||
"open_until": "Geöffnet bis",
|
||||
"opening_soon": "Öffnet"
|
||||
"closing": "Schließt {{relativeDateTime}}",
|
||||
"closing_soon_warning": "Schließt bald! Um {{time}} Uhr",
|
||||
"closing_today": "Schließt um {{time}} Uhr",
|
||||
"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": {
|
||||
|
||||
@@ -54,10 +54,15 @@
|
||||
},
|
||||
"common": {
|
||||
"openingHours": {
|
||||
"closed_until": "Closed until",
|
||||
"closing_soon": "Closing soon!",
|
||||
"open_until": "Open until",
|
||||
"opening_soon": "Opens"
|
||||
"closing": "Closing {{relativeDateTime}}",
|
||||
"closing_soon_warning": "Closing soon! At {{time}}",
|
||||
"closing_today": "Closing at {{time}}",
|
||||
"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": {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
body app-root {
|
||||
.title,
|
||||
.title-sub,
|
||||
.title[class*='sc-ion-label'],
|
||||
.title-sub[class*='sc-ion-label'] {
|
||||
.title[class*='sc-ion-label'] {
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-semi-bold);
|
||||
// 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 {
|
||||
color: var(--ion-color-primary);
|
||||
color: var(--ion-color-text);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user