Add basic scouting web page

This patch adds a basic web page. Ishan did the vast majority of the
work here. Future patches will integrate it with the rest of the
scouting web server.

Change-Id: I467bd16caade9c987022600c2b63e9fad20da1a3
Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Signed-off-by: Ishan Katpally <100026402@mvla.net>
Signed-off-by: Alex Perry <alex.perry96@gmail.com>
diff --git a/scouting/scouting_test.ts b/scouting/scouting_test.ts
index bb1c075..9ee9122 100644
--- a/scouting/scouting_test.ts
+++ b/scouting/scouting_test.ts
@@ -14,7 +14,7 @@
   }
 
   async getParagraphText() {
-    return (await this.waitForElement(element(by.css('h1')))).getText();
+    return (await this.waitForElement(element(by.css('.header')))).getText();
   }
 }
 
@@ -27,6 +27,6 @@
 
   it('should display: This is an app.', async () => {
     await page.navigateTo();
-    expect(await page.getParagraphText()).toEqual('This is an app.');
+    expect(await page.getParagraphText()).toEqual('Auto');
   });
 });
diff --git a/scouting/www/BUILD b/scouting/www/BUILD
index aa2ad7b..39246d8 100644
--- a/scouting/www/BUILD
+++ b/scouting/www/BUILD
@@ -14,12 +14,14 @@
     ]),
     angular_assets = glob([
         "*.ng.html",
+        "*.css",
     ]),
     compiler = "//tools:tsc_wrapped_with_angular",
     target_compatible_with = ["@platforms//cpu:x86_64"],
     use_angular_plugin = True,
     visibility = ["//visibility:public"],
     deps = [
+        "//scouting/www/entry",
         "@npm//@angular/animations",
         "@npm//@angular/common",
         "@npm//@angular/core",
diff --git a/scouting/www/app.ng.html b/scouting/www/app.ng.html
index fb9ba26..d7c1b22 100644
--- a/scouting/www/app.ng.html
+++ b/scouting/www/app.ng.html
@@ -1,3 +1,5 @@
-<h1>
-  This is an app.
-</h1>
+<!--Progress Bar-->
+<!--<div class="row">
+  <h1 class="text-end">Match {{matchNumber}}, Team {{teamNumber}}</h1>
+</div>-->
+<app-entry></app-entry>
\ No newline at end of file
diff --git a/scouting/www/app.ts b/scouting/www/app.ts
index f6247d3..c9d5ca1 100644
--- a/scouting/www/app.ts
+++ b/scouting/www/app.ts
@@ -5,4 +5,6 @@
   templateUrl: './app.ng.html',
 })
 export class App {
+  matchNumber: number = 1; //placeholder
+  teamNumber: number = 971; //placeholder
 }
diff --git a/scouting/www/app_module.ts b/scouting/www/app_module.ts
index 3e34a17..6a6fff0 100644
--- a/scouting/www/app_module.ts
+++ b/scouting/www/app_module.ts
@@ -1,6 +1,7 @@
 import {NgModule} from '@angular/core';
 import {BrowserModule} from '@angular/platform-browser';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+import {EntryModule} from './entry/entry.module';
 
 import {App} from './app';
 
@@ -9,6 +10,7 @@
   imports: [
     BrowserModule,
     BrowserAnimationsModule,
+    EntryModule,
   ],
   exports: [App],
   bootstrap: [App],
diff --git a/scouting/www/entry/BUILD b/scouting/www/entry/BUILD
new file mode 100644
index 0000000..8f46de7
--- /dev/null
+++ b/scouting/www/entry/BUILD
@@ -0,0 +1,20 @@
+load("@npm//@bazel/typescript:index.bzl", "ts_library")
+
+ts_library(
+    name = "entry",
+    srcs = glob([
+        "*.ts",
+    ]),
+    angular_assets = glob([
+        "*.ng.html",
+        "*.css",
+    ]),
+    compiler = "//tools:tsc_wrapped_with_angular",
+    target_compatible_with = ["@platforms//cpu:x86_64"],
+    use_angular_plugin = True,
+    visibility = ["//visibility:public"],
+    deps = [
+        "@npm//@angular/common",
+        "@npm//@angular/core",
+    ],
+)
diff --git a/scouting/www/entry/entry.component.css b/scouting/www/entry/entry.component.css
new file mode 100644
index 0000000..520b6d2
--- /dev/null
+++ b/scouting/www/entry/entry.component.css
@@ -0,0 +1,8 @@
+* {
+    margin: 10px;
+}
+
+textarea {
+    width: 300px;
+    height: 150px;
+}
\ No newline at end of file
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
new file mode 100644
index 0000000..21bdac4
--- /dev/null
+++ b/scouting/www/entry/entry.component.ts
@@ -0,0 +1,98 @@
+import { Component, OnInit } from '@angular/core';
+
+type Section = 'Auto'|'TeleOp'|'Climb'|'Defense'|'Review and Submit'|'Home'
+type Level = 'Low'|'Medium'|'High'|'Transversal'
+
+@Component({
+    selector: 'app-entry',
+    templateUrl: './entry.ng.html',
+    styleUrls: ['./entry.component.css']
+})
+export class EntryComponent {
+    section: Section = 'Auto'; //placeholder
+    autoUpperShotsMade: number = 0;
+    autoLowerShotsMade: number = 0;
+    autoShotsMissed: number = 0;
+    teleUpperShotsMade: number = 0;
+    teleLowerShotsMade: number = 0;
+    teleShotsMissed: number = 0;
+    defensePlayedOnScore: number = 50;
+    defensePlayedScore: number = 50;
+    level: Level;
+    proper: boolean = false;
+    climbed: boolean = false;
+
+    toggleProper() {
+        this.proper = !this.proper;
+    }
+
+    setLow() {
+        this.level = 'Low';
+    }
+
+    setMedium() {
+        this.level = 'Medium';
+    }
+
+    setHigh() {
+        this.level = 'High';
+    }
+
+    setTransversal() {
+        this.level = 'Transversal';
+    }
+
+    defensePlayedOnSlider(event) {
+        this.defensePlayedOnScore = event.target.value;
+    }
+
+    defensePlayedSlider(event) {
+        this.defensePlayedScore = event.target.value;
+    }
+
+    setClimbedTrue() {
+        this.climbed = true;
+    }
+
+    setClimbedFalse() {
+        this.climbed = false;
+    }
+
+    nextSection() {
+        if (this.section === 'Auto') {
+            this.section = 'TeleOp';
+        } else if (this.section === 'TeleOp') {
+            this.section = 'Climb';
+        } else if (this.section === 'Climb') {
+            this.section = 'Defense';
+        } else if (this.section === 'Defense') {
+            this.section = 'Review and Submit';
+        } else if (this.section === 'Review and Submit') {
+            this.section = 'Home';
+        }
+    }
+
+    adjustAutoUpper(by: number) {
+        this.autoUpperShotsMade = Math.max(0, this.autoUpperShotsMade + by);
+    }
+
+    adjustAutoLower(by: number) {
+        this.autoLowerShotsMade = Math.max(0, this.autoLowerShotsMade + by);
+    }
+
+    adjustAutoMissed(by: number) {
+        this.autoShotsMissed = Math.max(0, this.autoShotsMissed + by);
+    }
+
+    adjustTeleUpper(by: number) {
+        this.teleUpperShotsMade = Math.max(0, this.teleUpperShotsMade + by);
+    }
+
+    adjustTeleLower(by: number) {
+        this.teleLowerShotsMade = Math.max(0, this.teleLowerShotsMade + by);
+    }
+
+    adjustTeleMissed(by: number) {
+        this.teleShotsMissed = Math.max(0, this.teleShotsMissed + by);
+    }
+}
diff --git a/scouting/www/entry/entry.module.ts b/scouting/www/entry/entry.module.ts
new file mode 100644
index 0000000..d454c2e
--- /dev/null
+++ b/scouting/www/entry/entry.module.ts
@@ -0,0 +1,11 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {EntryComponent} from './entry.component';
+
+@NgModule({
+  declarations: [EntryComponent],
+  exports: [EntryComponent],
+  imports: [CommonModule],
+})
+export class EntryModule {
+}
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
new file mode 100644
index 0000000..c20edf9
--- /dev/null
+++ b/scouting/www/entry/entry.ng.html
@@ -0,0 +1,185 @@
+<div class="header">
+    <h2>{{section}}</h2>
+</div>
+
+<ng-container [ngSwitch]="section">
+    <div *ngSwitchCase="'Auto'" id="auto" class="container-fluid">
+        <div class="row">
+            <!--Image here-->
+            <h4>Image</h4>
+            <form>
+                <!--Choice for each ball location-->
+                <input type="radio" name="balls" value="1" id="ball-1"><label for="ball-1">Ball 1</label>
+                <input type="radio" name="balls" value="2" id="ball-2"><label for="ball-2">Ball 2</label><br>
+                <input type="radio" name="balls" value="3" id="ball-3"><label for="ball-3">Ball 3</label>
+                <input type="radio" name="balls" value="4" id="ball-4"><label for="ball-4">Ball 4</label>
+            </form>
+        </div>
+        <div class="row">
+            <!--Image here-->
+            <h4>Image</h4>
+            <form>
+                <input type="radio" name="quadrant" id="first" value="Quadrant 1">
+                <label for="first">Quadrant 1</label>
+                <input type="radio" name="quadrant" id="second" value="Quadrant 2">
+                <label for="second">Quadrant 2</label><br>
+                <input type="radio" name="quadrant" id="third" value="Quadrant 3">
+                <label for="third">Quadrant 3</label>
+                <input type="radio" name="quadrant" id="fourth" value="Quadrant 4">
+                <label for="fourth">Quadrant 4</label>
+            </form>
+        </div>
+        <div class="row justify-content-center">
+            <div class="col-sm">
+                <h4>Upper Shots Made</h4>
+                <button (click)="adjustAutoUpper(1)" class="btn btn-secondary">+</button>
+                <h3>{{autoUpperShotsMade}}</h3>
+                <button (click)="adjustAutoUpper(-1)" class="btn btn-secondary">-</button>
+            </div>
+
+            <div class="col-sm">
+                <h4>Lower Shots Made</h4>
+                <button (click)="adjustAutoLower(1)" class="col-xs btn btn-secondary">+</button>
+                <h3>{{autoLowerShotsMade}}</h3>
+                <button (click)="adjustAutoLower(-1)" class="btn btn-secondary">-</button>
+            </div>
+
+            <div class="col-sm">
+                <h4>Missed Shots</h4>
+                <button (click)="adjustAutoMissed(1)" class="btn btn-secondary">+</button>
+                <h3>{{autoShotsMissed}}</h3>
+                <button (click)="adjustAutoMissed(-1)" class="btn btn-secondary">-</button>
+            </div>
+        </div>
+        <div class="text-right">
+            <button class="btn btn-primary" (click)="nextSection()">Next</button>
+        </div>
+    </div>
+
+    <div *ngSwitchCase="'TeleOp'" id="teleop" class="container-fluid">
+        <div class="row justify-content-center">
+            <div class="col-sm">
+                <h4>Upper Shots Made</h4>
+                <button (click)="adjustTeleUpper(1)" class="btn btn-secondary">+</button>
+                <h3>{{teleUpperShotsMade}}</h3>
+                <button (click)="adjustTeleUpper(-1)" class="btn btn-secondary">-</button>
+            </div>
+
+            <div class="col-sm">
+                <h4>Lower Shots Made</h4>
+                <button (click)="adjustTeleLower(1)" class="btn btn-secondary">+</button>
+                <h3>{{teleLowerShotsMade}}</h3>
+                <button (click)="adjustTeleLower(-1)" class="btn btn-secondary">-</button>
+            </div>
+
+            <div class="col-sm">
+                <h4>Missed Shots</h4>
+                <button (click)="adjustTeleMissed(1)" class="btn btn-secondary">+</button>
+                <h3>{{teleShotsMissed}}</h3>
+                <button (click)="adjustTeleMissed(-1)" class="btn btn-secondary">-</button>
+            </div>
+        </div>
+        <div class="text-right">
+            <button class="btn btn-primary" (click)="nextSection()">Next</button>
+        </div>
+    </div>
+
+    <div *ngSwitchCase="'Climb'" id="climb" class="container-fluid">
+        <div class="row">
+            <form>
+                <input (click)="setClimbedFalse()" type="radio" name="climbing" id="continue"><label for="continue">Kept Shooting</label><br>
+                <input (click)="setClimbedTrue()" type="radio" name="climbing" id="climbed"><label for="climbed">Attempted to Climb</label><br>
+            </form>
+        </div>
+        <div *ngIf="climbed">
+            <h4>Bar Made</h4>
+            <form>
+                <input (click)="setLow()" type="radio" name="level" id="low"><label for="low">Low</label><br>
+                <input (click)="setMedium()" type="radio" name="level" id="medium"><label for="medium">Medium</label><br>
+                <input (click)="setHigh()" type="radio" name="level" id="high"><label for="high">High</label><br>
+                <input (click)="setTransversal()" type="radio" name="level" id="transversal"><label for="transversal">Transversal</label><br>
+                <input (click)="toggleProper()" type="checkbox" id="proper"><label for="proper">~10 seconds to attempt next level?</label>
+            </form>
+        </div>
+        <div class="row">
+            <h4>Comments</h4>
+            <textarea></textarea>
+        </div>
+        <button class="btn btn-primary" (click)="nextSection()">Next</button>
+    </div>
+
+    <div *ngSwitchCase="'Defense'" id="defense" class="container-fluid">
+        <h4 class="text-center">How much defense did other robots play on this robot?</h4>
+
+        <div class="row" style="min-height: 50px">
+            <div class="col">
+                <h6>None</h6>
+            </div>
+
+            <div class="col">
+                <input type="range" min="1" max="100" value="50" (input)="defensePlayedOnSlider($event)">
+            </div>
+
+            <div class="col">
+                <h6>A lot</h6>
+            </div>
+        </div>
+
+        <h6 class="text-center">{{defensePlayedOnScore}}</h6>
+
+        <h4 class="text-center">How much defense did this robot play?</h4>
+
+        <div class="row">
+
+            <div class="col">
+                <h6>None</h6>
+            </div>
+
+            <div class="col">
+                <input type="range" min="1" max="100" value="50" (input)="defensePlayedSlider($event)">
+            </div>
+
+            <div class="col">
+                <h6>A lot</h6>
+            </div>
+        </div>
+        <h6 class="text-center">{{defensePlayedScore}}</h6>
+
+        <button class="btn btn-primary" (click)="nextSection()">Next</button>
+    </div>
+
+    <div *ngSwitchCase="'Review and Submit'" id="review" class="container-fluid">
+        <h4>Auto</h4>
+        <ul>
+            <li>Upper Shots Made: {{autoUpperShotsMade}}</li>
+            <li>Lower Shots Made: {{autoLowerShotsMade}}</li>
+            <li>Missed Shots: {{autoShotsMissed}}</li>
+        </ul>
+
+        <h4>TeleOp</h4>
+        <ul>
+            <li>Upper Shots Made: {{teleUpperShotsMade}}</li>
+            <li>Lower Shots Made: {{teleLowerShotsMade}}</li>
+            <li>Missed Shots {{teleShotsMissed}}</li>
+        </ul>
+
+        <h4>Climb</h4>
+        <ul>
+            <div *ngIf="climbed">
+                <li *ngIf="climbed">Attempted to Climb?: Yes</li>
+                <li>Level: {{level}}</li>
+                <li *ngIf="proper">Proper Attempt: Yes</li>
+                <li *ngIf="!proper">Proper Attempt: No</li>
+            </div>
+            <li *ngIf="!climbed">Attempted to Climb: No</li>
+        </ul>
+
+        <h4>Defense</h4>
+        <ul>
+            <li>Defense Played On Rating: {{defensePlayedOnScore}}</li>
+            <li>Defense Played Raing: {{defensePlayedScore}}</li>
+        </ul>
+
+        <button class="btn btn-primary" (click)="nextSection()">Submit</button>
+    </div>
+</ng-container>
diff --git a/scouting/www/index.html b/scouting/www/index.html
index cbe8770..3a09dfd 100644
--- a/scouting/www/index.html
+++ b/scouting/www/index.html
@@ -1,7 +1,10 @@
+<!DOCTYPE html>
 <html>
   <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
     <base href="/">
     <script src="./npm/node_modules/zone.js/dist/zone.min.js"></script>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
   </head>
   <body>
     <my-app></my-app>