camera and sign components, submit code
This commit is contained in:
parent
f6a8010792
commit
15d7928439
7 changed files with 220 additions and 11 deletions
|
|
@ -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,
|
||||
|
|
|
|||
58
src/app/camera.component.ts
Normal file
58
src/app/camera.component.ts
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
72
src/app/sign.component.ts
Normal 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();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}]
|
||||
}]
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue