diff --git a/Client/package-lock.json b/Client/package-lock.json
index c414a3c..cfbde72 100644
--- a/Client/package-lock.json
+++ b/Client/package-lock.json
@@ -951,7 +951,8 @@
"@types/chart.js": {
"version": "2.9.7",
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.7.tgz",
- "integrity": "sha512-T+oRIWLPu6cXWYSTwihkeZLKk5V4U4O09Uqx4padQto1XVH7YafX4Z4YV1OIWnKbkqMn/4Cuj9ZwWcG6fnKK3A=="
+ "integrity": "sha512-T+oRIWLPu6cXWYSTwihkeZLKk5V4U4O09Uqx4padQto1XVH7YafX4Z4YV1OIWnKbkqMn/4Cuj9ZwWcG6fnKK3A==",
+ "dev": true
},
"@types/jasmine": {
"version": "2.8.15",
@@ -5997,6 +5998,11 @@
}
}
},
+ "luxon": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.22.0.tgz",
+ "integrity": "sha512-3sLvlfbFo+AxVEY3IqxymbumtnlgBwjDExxK60W3d+trrUzErNAz/PfvPT+mva+vEUrdIodeCOs7fB6zHtRSrw=="
+ },
"magic-string": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz",
diff --git a/Client/package.json b/Client/package.json
index fe2c3c2..c415639 100644
--- a/Client/package.json
+++ b/Client/package.json
@@ -20,11 +20,12 @@
"@angular/material": "^7.2.1",
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~7.2.0",
- "@angular/router": "~7.2.0",
+ "@angular/router": "~7.2.0",
"chart.js": "^2.9.3",
"chartjs-plugin-datalabels": "^0.7.0",
"core-js": "^2.5.4",
"hammerjs": "^2.0.8",
+ "luxon": "^1.22.0",
"rxjs": "~6.3.3",
"tslib": "^1.9.0",
"zone.js": "~0.8.26"
diff --git a/Client/src/app/app-routing.module.ts b/Client/src/app/app-routing.module.ts
index d55e06c..3636232 100644
--- a/Client/src/app/app-routing.module.ts
+++ b/Client/src/app/app-routing.module.ts
@@ -16,6 +16,7 @@ import { AddTransactionPageComponent } from './components/add-transaction-page/a
import { MissionaryFormPageComponent } from './components/missionary-form-page/missionary-form-page.component';
import { ContributorYearlyReportComponent } from './components/contributor-yearly-report/contributor-yearly-report.component';
import { ContributorAllReportsComponent } from './components/contributor-all-reports/contributor-all-reports.component';
+import { LiveStreamComponent } from './components/live-stream/live-stream.component';
const routes =
[
@@ -75,6 +76,10 @@ const routes =
path: 'camp',
component: CampPageComponent
},
+ {
+ path: 'live',
+ component: LiveStreamComponent
+ },
{
path: 'transactions/add',
component: AddTransactionPageComponent
diff --git a/Client/src/app/app.module.ts b/Client/src/app/app.module.ts
index 7c52391..39b754d 100644
--- a/Client/src/app/app.module.ts
+++ b/Client/src/app/app.module.ts
@@ -76,6 +76,7 @@ import { MissionaryFormPageComponent } from './components/missionary-form-page/m
import { MissionarySupportService } from './services/missionary-support-service';
import { ContributorYearlyReportComponent } from './components/contributor-yearly-report/contributor-yearly-report.component';
import { ContributorAllReportsComponent } from './components/contributor-all-reports/contributor-all-reports.component';
+import { LiveStreamComponent } from './components/live-stream/live-stream.component';
@@ -123,7 +124,8 @@ import { ContributorAllReportsComponent } from './components/contributor-all-rep
AddTransactionPopupComponent,
MissionaryFormPageComponent,
ContributorYearlyReportComponent,
- ContributorAllReportsComponent
+ ContributorAllReportsComponent,
+ LiveStreamComponent
],
imports: [
BrowserModule,
diff --git a/Client/src/app/components/home/countdown.ts b/Client/src/app/components/home/countdown.ts
new file mode 100644
index 0000000..4cc65c5
--- /dev/null
+++ b/Client/src/app/components/home/countdown.ts
@@ -0,0 +1,150 @@
+import { DateTime } from "luxon";
+
+export class Countdown {
+ public days: number = 0;
+ public hours: number = 0;
+ public minutes: number = 0;
+ public seconds: number = 0;
+ public liveDates: Date[] = [
+ DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 10, zone: 'America/Denver'}),
+ DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 11, zone: 'America/Denver'}),
+ DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 19, zone: 'America/Denver'})
+ ];
+ public showButton: boolean;
+ public showCounter: boolean = true;
+
+ public dateDisplay: string;
+ public dateDisplaySmall: string;
+
+ public get daysDisplay(): string {
+ return this.formatDisplay(this.days);
+ }
+
+ public get daysText(): string {
+ return this.days === 1 ? 'day ' : 'days';
+ }
+
+ public get hoursDisplay(): string {
+ return this.formatDisplay(this.hours);
+ }
+
+ public get hoursText(): string {
+ return this.hours === 1 ? 'hr ' : 'hrs';
+ }
+
+ public get minutesDisplay(): string {
+ return this.formatDisplay(this.minutes);
+ }
+
+ public get minutesText(): string {
+ return this.minutes === 1 ? 'min ' : 'mins';
+ }
+
+ public get secondsDisplay(): string {
+ return this.formatDisplay(this.seconds);
+ }
+
+ public get secondsText(): string {
+ return this.seconds === 1 ? 'sec ' : 'secs';
+ }
+
+ private clock;
+
+ constructor() {
+ if (this.liveDates.length == 0) return;
+ this.liveDates.sort((a, b) => {
+ if (a < b) return -1;
+ if (a === b) return 0;
+ return 1;
+ });
+ this.updateClock();
+ this.startClock();
+ }
+
+ private resetToZero() {
+ this.days = 0;
+ this.hours = 0;
+ this.minutes = 0;
+ this.seconds = 0;
+ }
+
+ private updateClock() {
+ this.showCounter = true;
+ var now = DateTime.local();
+ var nearestPast = this.getNearestPastDate(now);
+ if (nearestPast) {
+ var pastDiff = now.diff(nearestPast, ['minutes']);
+ if (pastDiff.minutes < 45) {
+ this.showButton = true;
+ this.dateDisplay = nearestPast.toLocaleString(DateTime.DATETIME_HUGE);
+ this.dateDisplaySmall = nearestPast.toLocaleString(DateTime.DATETIME_MED);
+ return;
+ }
+ }
+
+ this.showButton = false;
+ var nearestFuture = this.getNearestFutureDate(now);
+ if (!nearestFuture) {
+ this.stopClock();
+ this.resetToZero();
+ this.showCounter = false;
+ this.dateDisplay = '';
+ this.dateDisplaySmall = '';
+ return;
+ }
+ var minDiff = nearestFuture.diff(now, ['minutes']);
+ if (minDiff.minutes <= 10) {
+ this.showButton = true;
+ }
+
+ var hourDiff = nearestFuture.diff(now, ['hours']);
+ if (hourDiff.hours >= 48) {
+ this.showCounter = false;
+ this.dateDisplay = '';
+ this.dateDisplaySmall = '';
+ return;
+ }
+
+ var diff = nearestFuture.diff(now, ['days', 'hours', 'minutes', 'seconds']);
+ this.days = diff.days;
+ this.hours = diff.hours;
+ this.minutes = diff.minutes;
+ this.seconds = Math.floor(diff.seconds);
+ this.dateDisplay = nearestFuture.toLocaleString(DateTime.DATETIME_HUGE);
+ this.dateDisplaySmall = nearestFuture.toLocaleString(DateTime.DATETIME_MED)
+ }
+
+ private startClock() {
+ this.clock = setInterval(this.updateClock.bind(this), 1000);
+ }
+
+ private stopClock() {
+ clearInterval(this.clock);
+ }
+
+ private getNearestPastDate(now: DateTime): DateTime {
+ if (this.liveDates.length === 0) return null;
+ var now = now || DateTime.local();
+ var nearestIndex = this.liveDates.findIndex(d => d > now);
+ if (nearestIndex === 0) return null;
+ if (nearestIndex === -1) return this.liveDates[this.liveDates.length - 1];
+ return this.liveDates[nearestIndex - 1];
+ }
+
+ private getNearestFutureDate(now: DateTime): DateTime {
+ if (this.liveDates.length === 0) return null;
+ var now = now || DateTime.local();
+ var nearest = this.liveDates.find(d => d > now);
+ return nearest;
+ }
+
+ private formatDisplay(val: number): string {
+ if (val <= 0) {
+ return '00';
+ }
+ if (val < 10) {
+ return '0' + val.toString();
+ }
+ return val.toString();
+ }
+}
\ No newline at end of file
diff --git a/Client/src/app/components/home/home.component.css b/Client/src/app/components/home/home.component.css
index 26d607c..9e8575a 100644
--- a/Client/src/app/components/home/home.component.css
+++ b/Client/src/app/components/home/home.component.css
@@ -30,6 +30,117 @@ img.full {
bottom: 10%;
}
+#live-stream-container {
+ text-align: left;
+ position: absolute;
+ left: 10%;
+ right: 0;
+ bottom: 20%;
+}
+
+#title > .live {
+ display: inline-block;
+ background-color: red;
+ color: white;
+ padding: 0px 7px;
+ border-radius: 10px;
+}
+
+#live-date {
+ color: white;
+ font-weight: bold;
+ margin-top: 5px;
+}
+
+#live-stream-container > #title {
+ font-size: 25pt;
+ font-weight: bold;
+ color: white;
+ font-family: Franklin Gothic Medium,Franklin Gothic,ITC Franklin Gothic,Arial,sans-serif;
+}
+
+#countdown-container {
+ text-decoration: none;
+ position: relative;
+ margin-top: 7px;
+ display: inline-block;
+ font-size: 30pt;
+ font-weight: bold;
+ border-radius: 10px;
+ background-color: rgba(255, 255, 255, 1);
+ padding: 15px 20px;
+ -webkit-box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
+ -moz-box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
+ box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
+ border: 1px solid green;
+ font-family: Consolas,monaco,monospace;
+}
+
+/*Button*/
+#countdown-container.show-button {
+ background-color:#2dabf9;
+ color:#ffffff;
+ text-shadow:0px 1px 0px #263666;
+}
+#countdown-container.show-button:hover {
+ background-color:#0688fa;
+}
+#countdown-container.show-button:active {
+ position:relative;
+ top:1px;
+}
+
+/*End Button*/
+
+#countdown-container .text {
+ font-size: 10pt;
+}
+
+.opacity-zero {
+ opacity: 0;
+}
+
+#live-button {
+ position: absolute;
+ font-size: 25pt;
+ width: 100%;
+ height: 100%;
+}
+
+@media(max-width:900px){
+ #live-stream-container > #title {
+ font-size: 15pt;
+ }
+ #countdown-container {
+ font-size: 20pt;
+ }
+}
+
+.display-sm {
+ display: none;
+}
+
+@media(max-width:600px){
+ #live-stream-container {
+ left: 5%;
+ right: 5%;
+ bottom: 5%
+ }
+ #live-stream-container > #title {
+ font-size: 11pt;
+ }
+ #countdown-container {
+ font-size: 13pt;
+ }
+ .display-none-sm {
+ display: none;
+ }
+ .display-sm {
+ display: block;
+ }
+}
+
+
#action-button {
font-size: 16pt;
max-width: 100%;
diff --git a/Client/src/app/components/home/home.component.html b/Client/src/app/components/home/home.component.html
index 89b809b..041dbe8 100644
--- a/Client/src/app/components/home/home.component.html
+++ b/Client/src/app/components/home/home.component.html
@@ -2,6 +2,35 @@