camera and sign components, submit code

This commit is contained in:
Gundersen 2022-03-01 10:16:58 -06:00
commit 15d7928439
7 changed files with 220 additions and 11 deletions

View file

@ -7,6 +7,8 @@ import { FormComponent } from './form.component';
import { TextComponent } from './text.component';
import { RadioComponent } from './radio.component';
import { StepComponent } from './step.component';
import { CameraComponent } from './camera.component';
import { SignComponent } from './sign.component';
@NgModule({
declarations: [
@ -15,6 +17,8 @@ import { StepComponent } from './step.component';
TextComponent,
RadioComponent,
StepComponent,
CameraComponent,
SignComponent,
],
imports: [
BrowserModule,

View file

@ -0,0 +1,58 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-camera',
template: `
<div class="camera">
<video id="video">Unable to access camera.</video>
<img [src]="this.field.value" />
<button (click)="capture()">Take photo</button>
</div>
`
})
export class CameraComponent implements OnInit {
@Input() field: Field;
@Output() update: EventEmitter<null> = new EventEmitter();
video: HTMLVideoElement;
ngOnInit() { console.log("Smile!"); }
ngAfterViewInit() {
this.video = document.getElementById("video") as HTMLVideoElement;
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then((stream) => {
this.video.srcObject = stream;
this.video.play();
});
}
capture() {
const canvas = document.createElement("canvas") as HTMLCanvasElement;
canvas.width = this.video.videoWidth;
canvas.height = this.video.videoHeight;
canvas
.getContext("2d")
.drawImage(this.video, 0, 0, canvas.width, canvas.height);
this.field.ok = true;
this.field.value = canvas.toDataURL();
this.update.emit();
}
}

View file

@ -15,6 +15,7 @@ import { Component, OnInit, Input } from '@angular/core';
></app-step>
<button
class="bar"
[class.active]="form.step > 0"
(click)="back()"
>
@ -22,6 +23,7 @@ import { Component, OnInit, Input } from '@angular/core';
</button>
<button
class="bar"
[class.active]="form.steps[form.step].ok"
(click)="next()"
>
@ -45,17 +47,41 @@ export class FormComponent implements OnInit {
this.form.step == this.form.steps.length - 1 ?
this.submit() :
this.form.step++
this.form.step++;
}
back() { this.form.step--; }
submit() {
async submit() {
console.log("Submitting", this.form);
this.set();
const results = {};
this.form.steps.forEach((s: Step) => {
s.fields.forEach((f: Field) => {
results[f.id] = f.value;
});
});
try {
const res = await fetch(this.form.submit, results);
if (res.ok) {
this.set();
} else {
alert("Backend does't like you.");
}
} catch (e) { alert("Something went wrong."); }
}

72
src/app/sign.component.ts Normal file
View file

@ -0,0 +1,72 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-sign',
template: `
<div class="sign">
<canvas id="pad"></canvas>
<button (click)="clear()">Clear</button>
</div>
`
})
export class SignComponent implements OnInit {
@Input() field: Field;
@Output() update: EventEmitter<null> = new EventEmitter();
pad: HTMLCanvasElement;
ngOnInit() { console.log("Sign your name!"); }
ngAfterViewInit() {
this.pad = document.getElementById("pad") as HTMLCanvasElement;
const ctx = this.pad.getContext('2d');
this.pad.width = 300;
this.pad.height = 100;
ctx.lineWidth = 3;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
let active, cursor;
this.pad.onmousedown = (e) => {
active = true;
cursor = { x: e.offsetX, y: e.offsetY };
}
this.pad.onmousemove = (e) => {
if (active) {
ctx.beginPath();
ctx.moveTo(cursor.x, cursor.y);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
cursor = { x: e.offsetX, y: e.offsetY };
}
}
this.pad.onmouseup = (_e) => {
active = false;
this.field.value = this.pad.toDataURL();
this.field.ok = true;
this.update.emit();
};
}
clear() {
this.pad.getContext('2d').clearRect(0, 0, this.pad.width, this.pad.height);
this.field.value = null;
this.field.ok = false;
this.update.emit();
};
}

View file

@ -23,6 +23,20 @@ import { Component, OnInit, Input } from '@angular/core';
></app-radio>
<app-camera *ngSwitchCase="'camera'"
[field]="field"
(update)="update()"
></app-camera>
<app-sign *ngSwitchCase="'sign'"
[field]="field"
(update)="update()"
></app-sign>
</div>
</div>

View file

@ -35,6 +35,28 @@ export const checkout: Form = {
options: { choices: ["mouse", "keyboard", "monitor", "chair"] }
}]
},
{
ok: false,
prompt: "Take a photo.",
fields: [{
ok: false,
type: "camera",
id: "photo",
value: null,
options: null
}]
},
{
ok: false,
prompt: "Sign your name.",
fields: [{
ok: false,
type: "sign",
id: "signiture",
value: null,
options: null
}]
},
{
ok: false,
prompt: "Would you like a confirmation email?",
@ -81,13 +103,13 @@ export const checkin: Form = {
},
{
ok: false,
prompt: "Would you like a confirmation email?",
prompt: "Sign your name.",
fields: [{
ok: false,
type: "radio",
id: "confirmation",
type: "sign",
id: "signiture",
value: null,
options: { choices: ["yes", "no"] }
options: null
}]
}]

View file

@ -1,5 +1,18 @@
.bar {
pointer-events: none;
}
.active {
pointer-events: auto;
color: blue;
border-color: blue;
}
color: blue;
}
video, img {
width: 100px;
}
#pad {
background-color: white;
border: 2px solid black;
}