Textbox:
diff --git a/src/app/progress-stepper/progress-stepper.component.html b/src/app/progress-stepper/progress-stepper.component.html
index f06f1f2..d8b7665 100644
--- a/src/app/progress-stepper/progress-stepper.component.html
+++ b/src/app/progress-stepper/progress-stepper.component.html
@@ -1,56 +1,64 @@
- @for (item of [{status: 'completed'}, {status: 'in progress'}, test]; track item; let i =
- $index) {
-
-
-
-
-
-
-
-
- step {{ i + 1 }}
- {{ item.status }}
-
+ @for (item of steps; track item; let index = $index) {
+
+
-
+
+
+
+
+
+ {{ item }}
+ status.progressIndex && status.progressStatus === STATUS.Canceled,
+ }">
+ {{ statusToLabel(indexStatus(index)) }}
+
+
+
}
-
-
next
-
prev
+
+
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/progress-stepper/progress-stepper.component.scss b/src/app/progress-stepper/progress-stepper.component.scss
index 52f7ae7..e02b65b 100644
--- a/src/app/progress-stepper/progress-stepper.component.scss
+++ b/src/app/progress-stepper/progress-stepper.component.scss
@@ -1,3 +1,11 @@
+$checkboxWidth: 33px;
+$checkboxHeight: 33px;
+
+$color-in-progress: #234dc2;
+$color-completed: #23c274;
+$color-canceled: #c23323;
+$color-selected-step: rebeccapurple;
+
.step-progress {
margin-bottom: 1rem;
}
@@ -9,12 +17,12 @@
width: 100%;
padding: 30px;
box-sizing: border-box;
- position: relative;
svg#checkbox {
- width: 33px;
- height: 33px;
- stroke: #23c274;
+ position: relative;
+ width: $checkboxWidth;
+ height: $checkboxHeight;
+ stroke: $color-completed;
stroke-width: 6;
.circle {
@@ -36,12 +44,16 @@
}
.selection-circle {
- // stroke-dasharray: 320;
- // stroke-dashoffset: 320;
- stroke: rebeccapurple;
+ stroke-dasharray: 320;
+ stroke-dashoffset: 320;
+ stroke: $color-selected-step;
transition:
stroke-dashoffset 0.5s,
fill 0.5s 0.3s cubic-bezier(0.45, 0, 0.55, 1);
+
+ &.selected {
+ stroke-dashoffset: 0;
+ }
}
.check {
@@ -51,6 +63,13 @@
fill: none;
transition: all 0.5s 0.5s cubic-bezier(0.45, 0, 0.55, 1);
}
+ .fail {
+ stroke-dasharray: 70;
+ stroke-dashoffset: 70;
+ stroke: #fff;
+ fill: none;
+ transition: all 0.5s 0.5s cubic-bezier(0.45, 0, 0.55, 1);
+ }
}
}
@@ -60,9 +79,48 @@
align-items: center;
position: relative;
+ &.selectable {
+ .hover-box:hover,
+ .hover-box:has(+ .info:hover) {
+ &::before {
+ $hoverOffset: 7px;
+
+ content: "";
+ position: absolute;
+ background: #000;
+ top: calc($hoverOffset / -2);
+ left: calc($hoverOffset / -2);
+ width: calc($checkboxWidth + $hoverOffset);
+ height: calc($checkboxHeight + $hoverOffset);
+
+ border-radius: calc($hoverOffset * 0.5);
+ z-index: 20;
+ opacity: 20%;
+ }
+ }
+
+ .hover-box {
+ position: relative;
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ .info:hover {
+ cursor: pointer;
+ }
+ }
+
+ &.first {
+ flex-grow: 0.05;
+ }
+
.info {
position: absolute;
- bottom: -40px;
+ bottom: -30px;
+ right: 0;
+ text-align: right;
display: grid;
grid-template-columns: max-content;
@@ -71,23 +129,38 @@
font-size: 11px;
display: inline-block;
margin-left: 5px;
- padding: 2px 10px;
transform: translateY(6px);
font-weight: 500;
color: currentColor;
- background: #eee;
- border-radius: 20px;
- transition: background-color 0.1s ease-in-out;
- }
+ transition:
+ opacity 0.5s,
+ fill 0.5s 0.3s cubic-bezier(0.45, 0, 0.55, 1);
- span.progress-info.in-progress {
- background-color: #234dc2;
- color: #fff;
- }
+ span {
+ padding: 2px 10px;
+ background: #eee;
+ border-radius: 20px;
+ transition: background-color 0.1s ease-in-out;
+ }
- span.progress-info.completed {
- background-color: #23c274;
- color: #fff;
+ &.never-called {
+ opacity: 0;
+ }
+
+ &.in-progress span {
+ background-color: $color-in-progress;
+ color: #fff;
+ }
+
+ &.completed span {
+ background-color: $color-completed;
+ color: #fff;
+ }
+
+ &.canceled span {
+ background-color: $color-canceled;
+ color: #fff;
+ }
}
span.step {
@@ -102,7 +175,7 @@
}
.progress-line {
- width: 140px;
+ width: 10px;
flex-grow: 1;
margin: 0 10px;
height: 4px;
@@ -116,38 +189,58 @@
width: 0%;
transition: all 0.5s 0.5s cubic-bezier(0.45, 0, 0.55, 1);
}
-}
-.progress-line.active {
- .progress-percent {
- background: #234dc2;
- width: 50%;
+ &.active .progress-percent {
+ background: $color-in-progress;
+ // width: 50%;
+ width: var(--progress);
}
-}
-.progress-line.complete {
- .progress-percent {
+ &.complete .progress-percent {
width: 100%;
- background: #23c274;
+ background: $color-completed;
+ }
+
+ &.canceled .progress-percent {
+ width: 0;
}
}
-.check-box.active {
- svg#checkbox {
- .circle {
- fill: #234dc2;
+.check-box {
+ &.active {
+ svg#checkbox {
+ .circle {
+ fill: $color-in-progress;
+ }
}
}
-}
-.check-box.complete {
- svg#checkbox {
- .circle {
- stroke-dashoffset: 0;
- fill: #23c274;
- }
- .check {
- stroke-dashoffset: 0;
+ &.complete {
+ svg#checkbox {
+ .circle {
+ // stroke-dashoffset: 0;
+ fill: $color-completed;
+ }
+
+ .check {
+ stroke-dashoffset: 0;
+ }
+ }
+ }
+
+ &.canceled {
+ svg#checkbox {
+ .circle {
+ fill: $color-canceled;
+ }
+
+ .inner-circle {
+ r: 0;
+ }
+
+ .fail {
+ stroke-dashoffset: 0;
+ }
}
}
}
diff --git a/src/app/progress-stepper/progress-stepper.component.ts b/src/app/progress-stepper/progress-stepper.component.ts
index 5dd7a62..db76da8 100644
--- a/src/app/progress-stepper/progress-stepper.component.ts
+++ b/src/app/progress-stepper/progress-stepper.component.ts
@@ -1,14 +1,61 @@
-import { NgClass } from '@angular/common';
-import { Component } from '@angular/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+export enum Status {
+ Open = 'open',
+ InProgress = 'in-progress',
+ Completed = 'completed',
+ Canceled = 'canceled'
+}
+
+export interface ProgressStatus {
+ progressIndex: number,
+ progressStatus: Status.InProgress | Status.Canceled,
+ progressPercent: number,
+}
@Component({
selector: 'app-progress-stepper',
- imports: [NgClass],
+ imports: [],
templateUrl: './progress-stepper.component.html',
styleUrl: './progress-stepper.component.scss'
})
export class ProgressStepperComponent {
selectedIndex = 0;
+ STATUS = Status;
- test = { status: 'Offen' };
+ @Input() steps: string[] = [];
+ @Input() status: ProgressStatus = { progressIndex: 0, progressStatus: Status.Canceled, progressPercent: 50 }
+
+ @Output() selectionChange: EventEmitter
= new EventEmitter();
+
+ selectStep(index: number) {
+ if (index <= this.status.progressIndex)
+ this.selectedIndex = index;
+
+ this.selectionChange.emit(index)
+ }
+
+ indexStatus(index: number): Status {
+ if (index < this.status.progressIndex)
+ return Status.Completed;
+ else if (index === this.status.progressIndex)
+ if (this.status.progressStatus === Status.InProgress)
+ return Status.InProgress;
+ else return Status.Canceled;
+ else
+ return Status.Open
+ }
+
+ statusToLabel(status: Status): string {
+ switch (status) {
+ case Status.Open: return 'Offen';
+ case Status.InProgress: return 'In Bearbeitung';
+ case Status.Canceled: return 'Verweigert';
+ case Status.Completed: return 'Fertig';
+ }
+ }
+
+ get getProgress(): string {
+ return `${Math.min(Math.max(this.status.progressPercent, 0), 100)}%`
+ }
}