diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index be757b7..7057e34 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -3,7 +3,6 @@ import {Routes, RouterModule} from '@angular/router'
import {CatalogComponent} from './pages/catalog/catalog.component'
import {AdministrationComponent} from './pages/administration/administration.component'
import {MiscComponent} from './pages/others/misc.component'
-import {TouchupkitComponent} from './pages/others/touchupkit/touchupkit.component'
const routes: Routes = [{
@@ -49,12 +48,12 @@ const routes: Routes = [{
path: 'misc',
component: MiscComponent,
children: [{
- path: 'touchupkit',
- component: TouchupkitComponent
+ path: 'touch-up-kit',
+ loadChildren: () => import('./modules/touch-up-kit/touch-up-kit.module').then(m => m.TouchUpKitModule)
}, {
path: '',
pathMatch: 'full',
- redirectTo: 'touchupkit'
+ redirectTo: 'touch-up-kit'
}]
}]
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 9de024d..c90abde 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,30 +1,34 @@
-import {DomSanitizer} from '@angular/platform-browser';
-import {NgModule} from '@angular/core';
+import {DomSanitizer} from '@angular/platform-browser'
+import {NgModule} from '@angular/core'
-import {AppRoutingModule} from './app-routing.module';
-import {AppComponent} from './app.component';
-import {MatIconRegistry} from "@angular/material/icon";
-import {SharedModule} from "./modules/shared/shared.module";
-import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
-import {CatalogComponent} from './pages/catalog/catalog.component';
-import {CompanyModule} from './modules/company/company.module';
-import { AdministrationComponent } from './pages/administration/administration.component';
-import { MiscComponent } from './pages/others/misc.component';
-import { TouchupkitComponent } from './pages/others/touchupkit/touchupkit.component';
+import {AppRoutingModule} from './app-routing.module'
+import {AppComponent} from './app.component'
+import {MatIconRegistry} from '@angular/material/icon'
+import {SharedModule} from './modules/shared/shared.module'
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations'
+import {CatalogComponent} from './pages/catalog/catalog.component'
+import {CompanyModule} from './modules/company/company.module'
+import {AdministrationComponent} from './pages/administration/administration.component'
+import {MiscComponent} from './pages/others/misc.component'
+import {CreTablesModule} from './modules/shared/components/tables/tables.module'
+import {CreButtonsModule} from './modules/shared/components/buttons/buttons.module'
+import {TouchUpKitModule} from './modules/touch-up-kit/touch-up-kit.module'
@NgModule({
declarations: [
AppComponent,
CatalogComponent,
AdministrationComponent,
- MiscComponent,
- TouchupkitComponent
+ MiscComponent
],
imports: [
AppRoutingModule,
SharedModule,
BrowserAnimationsModule,
- CompanyModule
+ CompanyModule,
+ CreTablesModule,
+ CreButtonsModule,
+ TouchUpKitModule
],
providers: [],
bootstrap: [AppComponent]
diff --git a/src/app/modules/colors/components/recipe-info/recipe-info.component.html b/src/app/modules/colors/components/recipe-info/recipe-info.component.html
index 5e4831a..ba42447 100644
--- a/src/app/modules/colors/components/recipe-info/recipe-info.component.html
+++ b/src/app/modules/colors/components/recipe-info/recipe-info.component.html
@@ -1,17 +1,12 @@
{{recipe.company.name}} - {{recipe.name}}
-
+
Échantillon #{{recipe.sample}}
-
Approuvée le {{recipe.approbationDate}}
+
Approuvée le {{approbationDate}}
Non approuvée
diff --git a/src/app/modules/colors/components/recipe-info/recipe-info.component.ts b/src/app/modules/colors/components/recipe-info/recipe-info.component.ts
index 35145bc..6a619d7 100644
--- a/src/app/modules/colors/components/recipe-info/recipe-info.component.ts
+++ b/src/app/modules/colors/components/recipe-info/recipe-info.component.ts
@@ -1,5 +1,6 @@
import {AfterViewInit, Component, Input} from '@angular/core'
import {getRecipeLuma, recipeApprobationExpired, Recipe} from '../../../shared/model/recipe.model'
+import {formatDate} from '../../../shared/utils/utils'
@Component({
selector: 'cre-recipe-info',
@@ -13,15 +14,14 @@ export class RecipeInfoComponent implements AfterViewInit {
isBPacExtensionInstalled = false
ngAfterViewInit(): void {
-
this.isBPacExtensionInstalled = document.querySelectorAll('.bpac-extension-installed').length > 0
}
+ get approbationDate(): string {
+ return formatDate(this.recipe.approbationDate)
+ }
+
get isApprobationExpired(): boolean {
return recipeApprobationExpired(this.recipe)
}
-
- get isDarkColor(): boolean {
- return getRecipeLuma(this.recipe) < 100
- }
}
diff --git a/src/app/modules/colors/pages/explore/explore.component.ts b/src/app/modules/colors/pages/explore/explore.component.ts
index 89665ec..1299087 100644
--- a/src/app/modules/colors/pages/explore/explore.component.ts
+++ b/src/app/modules/colors/pages/explore/explore.component.ts
@@ -13,6 +13,7 @@ import {GroupService} from '../../../groups/services/group.service'
import {AppState} from '../../../shared/app-state'
import {AccountService} from '../../../accounts/services/account.service'
import {Permission} from '../../../shared/model/user'
+import {Title} from '@angular/platform-browser'
@Component({
selector: 'cre-explore',
@@ -49,6 +50,7 @@ export class ExploreComponent extends ErrorHandlingComponent {
private alertService: AlertService,
private accountService: AccountService,
private appState: AppState,
+ private titleService: Title,
errorService: ErrorService,
router: Router,
activatedRoute: ActivatedRoute
@@ -68,6 +70,7 @@ export class ExploreComponent extends ErrorHandlingComponent {
id,
r => {
this.recipe = r
+ this.titleService.setTitle(r.name)
if (recipeMixCount(this.recipe) <= 0 || recipeStepCount(this.recipe) <= 0) {
this.alertService.pushWarning('Cette recette n\'est pas complète')
diff --git a/src/app/modules/colors/services/recipe.service.ts b/src/app/modules/colors/services/recipe.service.ts
index 5e80f25..1cda0ce 100644
--- a/src/app/modules/colors/services/recipe.service.ts
+++ b/src/app/modules/colors/services/recipe.service.ts
@@ -17,6 +17,10 @@ export class RecipeService {
return this.api.get
('/recipe')
}
+ getAllByName(name: string): Observable {
+ return this.api.get(`/recipe?name=${name}`)
+ }
+
get allSortedByCompany(): Observable<{ company: string, recipes: Recipe[] }[]> {
return this.all.pipe(map(recipes => {
const mapped = []
diff --git a/src/app/modules/shared/components/action-bar/action-bar.html b/src/app/modules/shared/components/action-bar/action-bar.html
new file mode 100644
index 0000000..4bad334
--- /dev/null
+++ b/src/app/modules/shared/components/action-bar/action-bar.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/app/modules/shared/components/action-bar/action-bar.module.ts b/src/app/modules/shared/components/action-bar/action-bar.module.ts
new file mode 100644
index 0000000..5188c1b
--- /dev/null
+++ b/src/app/modules/shared/components/action-bar/action-bar.module.ts
@@ -0,0 +1,15 @@
+import {NgModule} from '@angular/core'
+import {CreActionBar, CreActionGroup} from './action-bar'
+
+@NgModule({
+ exports: [
+ CreActionBar,
+ CreActionGroup
+ ],
+ declarations: [
+ CreActionBar,
+ CreActionGroup
+ ]
+})
+export class CreActionBarModule {
+}
diff --git a/src/app/modules/shared/components/action-bar/action-bar.ts b/src/app/modules/shared/components/action-bar/action-bar.ts
new file mode 100644
index 0000000..506bed9
--- /dev/null
+++ b/src/app/modules/shared/components/action-bar/action-bar.ts
@@ -0,0 +1,14 @@
+import {Component} from '@angular/core'
+
+@Component({
+ selector: 'cre-action-group',
+ templateUrl: 'action-group.html',
+ styleUrls: ['action-group.sass']
+})
+export class CreActionGroup {}
+
+@Component({
+ selector: 'cre-action-bar',
+ templateUrl: 'action-bar.html'
+})
+export class CreActionBar {}
diff --git a/src/app/modules/shared/components/action-bar/action-group.html b/src/app/modules/shared/components/action-bar/action-group.html
new file mode 100644
index 0000000..dfdbcc7
--- /dev/null
+++ b/src/app/modules/shared/components/action-bar/action-group.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/app/modules/shared/components/action-bar/action-group.sass b/src/app/modules/shared/components/action-bar/action-group.sass
new file mode 100644
index 0000000..4c50bf7
--- /dev/null
+++ b/src/app/modules/shared/components/action-bar/action-group.sass
@@ -0,0 +1,4 @@
+div
+ display: flex
+ flex-direction: row
+ gap: 1rem
diff --git a/src/app/modules/shared/components/buttons/buttons.module.ts b/src/app/modules/shared/components/buttons/buttons.module.ts
new file mode 100644
index 0000000..1dd694f
--- /dev/null
+++ b/src/app/modules/shared/components/buttons/buttons.module.ts
@@ -0,0 +1,22 @@
+import {NgModule} from '@angular/core'
+import {CreAccentButtonComponent, CreButtonComponent, CrePrimaryButtonComponent, CreWarnButtonComponent} from './buttons'
+import {MatButtonModule} from '@angular/material/button'
+
+@NgModule({
+ declarations: [
+ CreButtonComponent,
+ CrePrimaryButtonComponent,
+ CreAccentButtonComponent,
+ CreWarnButtonComponent
+ ],
+ imports: [
+ MatButtonModule
+ ],
+ exports: [
+ CrePrimaryButtonComponent,
+ CreAccentButtonComponent,
+ CreWarnButtonComponent
+ ]
+})
+export class CreButtonsModule {
+}
diff --git a/src/app/modules/shared/components/buttons/buttons.ts b/src/app/modules/shared/components/buttons/buttons.ts
new file mode 100644
index 0000000..7b3679e
--- /dev/null
+++ b/src/app/modules/shared/components/buttons/buttons.ts
@@ -0,0 +1,51 @@
+import {Component, Input} from '@angular/core'
+import {ThemePalette} from '@angular/material/core'
+
+@Component({
+ selector: 'cre-button',
+ template: `
+
+ `
+})
+export class CreButtonComponent {
+ @Input() color: ThemePalette
+ @Input() disabled = false
+}
+
+@Component({
+ selector: 'cre-primary-button',
+ template: `
+
+
+
+ `
+})
+export class CrePrimaryButtonComponent {
+ @Input() disabled = false
+}
+
+@Component({
+ selector: 'cre-accent-button',
+ template: `
+
+
+
+ `
+})
+export class CreAccentButtonComponent {
+ @Input() disabled = false
+}
+
+@Component({
+ selector: 'cre-warn-button',
+ template: `
+
+
+
+ `
+})
+export class CreWarnButtonComponent {
+ @Input() disabled = false
+}
diff --git a/src/app/modules/shared/components/color-preview/color-preview.html b/src/app/modules/shared/components/color-preview/color-preview.html
new file mode 100644
index 0000000..76b6bf6
--- /dev/null
+++ b/src/app/modules/shared/components/color-preview/color-preview.html
@@ -0,0 +1,6 @@
+
diff --git a/src/app/modules/shared/components/color-preview/color-preview.sass b/src/app/modules/shared/components/color-preview/color-preview.sass
new file mode 100644
index 0000000..28343ed
--- /dev/null
+++ b/src/app/modules/shared/components/color-preview/color-preview.sass
@@ -0,0 +1,20 @@
+.recipe-color-circle
+ color: black
+ width: 2.2rem
+ height: 2.2rem
+ border-radius: 1.1rem
+ margin-left: 1rem
+ font-size: 13px
+
+ &.dark-mode
+ color: white
+ width: 2.3rem
+ height: 2.3rem
+ border: solid 1px white
+
+ div
+ position: absolute
+ width: 2rem
+ text-align: center
+ margin-top: 7px
+ margin-left: 1px
diff --git a/src/app/modules/shared/components/color-preview/color-preview.ts b/src/app/modules/shared/components/color-preview/color-preview.ts
new file mode 100644
index 0000000..d713ec2
--- /dev/null
+++ b/src/app/modules/shared/components/color-preview/color-preview.ts
@@ -0,0 +1,15 @@
+import {getRecipeLuma, Recipe} from '../../model/recipe.model'
+import {Component, Input} from '@angular/core'
+
+@Component({
+ selector: 'cre-color-preview',
+ templateUrl: 'color-preview.html',
+ styleUrls: ['color-preview.sass']
+})
+export class CreColorPreview {
+ @Input() recipe: Recipe
+
+ get isDarkColor(): boolean {
+ return getRecipeLuma(this.recipe) < 100
+ }
+}
diff --git a/src/app/modules/shared/components/forms/form.html b/src/app/modules/shared/components/forms/form.html
new file mode 100644
index 0000000..1d6e89b
--- /dev/null
+++ b/src/app/modules/shared/components/forms/form.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/shared/components/forms/forms.module.ts b/src/app/modules/shared/components/forms/forms.module.ts
new file mode 100644
index 0000000..2ee4a91
--- /dev/null
+++ b/src/app/modules/shared/components/forms/forms.module.ts
@@ -0,0 +1,28 @@
+import {NgModule} from '@angular/core'
+import {CreFormActions, CreFormComponent, CreFormContent, CreFormTitle} from './forms'
+import {MatCardModule} from '@angular/material/card'
+import {CommonModule} from '@angular/common'
+import {MatButtonModule} from '@angular/material/button'
+import {ReactiveFormsModule} from '@angular/forms'
+
+@NgModule({
+ declarations: [
+ CreFormComponent,
+ CreFormTitle,
+ CreFormContent,
+ CreFormActions
+ ],
+ exports: [
+ CreFormComponent,
+ CreFormTitle,
+ CreFormContent,
+ CreFormActions
+ ],
+ imports: [
+ MatCardModule,
+ CommonModule,
+ MatButtonModule,
+ ReactiveFormsModule
+ ]
+})
+export class CreFormsModule {}
diff --git a/src/app/modules/shared/components/forms/forms.sass b/src/app/modules/shared/components/forms/forms.sass
new file mode 100644
index 0000000..fffedc8
--- /dev/null
+++ b/src/app/modules/shared/components/forms/forms.sass
@@ -0,0 +1,10 @@
+cre-form
+ display: block
+
+ mat-card
+ width: inherit
+
+ cre-form-actions
+ display: flex
+ flex-direction: row
+ gap: 1rem
diff --git a/src/app/modules/shared/components/forms/forms.ts b/src/app/modules/shared/components/forms/forms.ts
new file mode 100644
index 0000000..5770d23
--- /dev/null
+++ b/src/app/modules/shared/components/forms/forms.ts
@@ -0,0 +1,51 @@
+import {Component, ContentChild, Directive, Input, OnInit, ViewEncapsulation} from '@angular/core'
+import {FormBuilder, FormGroup} from '@angular/forms'
+
+@Directive({
+ selector: 'cre-form-title'
+})
+export class CreFormTitle {
+}
+
+@Directive({
+ selector: 'cre-form-content'
+})
+export class CreFormContent {
+}
+
+@Directive({
+ selector: 'cre-form-actions'
+})
+export class CreFormActions {
+
+}
+
+@Component({
+ selector: 'cre-form',
+ templateUrl: './form.html',
+ styleUrls: ['forms.sass'],
+ encapsulation: ViewEncapsulation.None
+})
+export class CreFormComponent implements OnInit {
+ @ContentChild(CreFormActions) formActions: CreFormActions
+ @Input() formControls: { [key: string]: any }
+
+ form: FormGroup
+
+ constructor(
+ private formBuilder: FormBuilder
+ ) {
+ }
+
+ ngOnInit(): void {
+ this.form = this.formBuilder.group(this.formControls)
+ }
+
+ get hasActions(): boolean {
+ return this.formActions === true
+ }
+
+ get invalid(): boolean {
+ return !this.form || this.form.invalid
+ }
+}
diff --git a/src/app/modules/shared/components/info-banner/info-banner.component.sass b/src/app/modules/shared/components/info-banner/info-banner.component.sass
new file mode 100644
index 0000000..558af2c
--- /dev/null
+++ b/src/app/modules/shared/components/info-banner/info-banner.component.sass
@@ -0,0 +1,16 @@
+@import "~src/custom-theme"
+
+.info-banner-wrapper
+ background-color: $color-primary
+ color: $light-primary-text
+ padding: 1rem
+
+.info-banner-section-wrapper
+ margin-right: 3rem
+
+h3
+ text-decoration: underline
+ font-weight: bold
+
+p
+ margin-bottom: 0
diff --git a/src/app/modules/shared/components/info-banner/info-banner.component.ts b/src/app/modules/shared/components/info-banner/info-banner.component.ts
new file mode 100644
index 0000000..7a0b379
--- /dev/null
+++ b/src/app/modules/shared/components/info-banner/info-banner.component.ts
@@ -0,0 +1,49 @@
+import {Component} from '@angular/core'
+
+@Component({
+ selector: 'info-banner',
+ template: `
+
+
+
+ `,
+ styleUrls: ['info-banner.component.sass']
+})
+export class InfoBannerComponent {
+}
+
+@Component({
+ selector: 'info-banner-title',
+ template: `
+
+
+
+ `,
+ styleUrls: ['info-banner.component.sass']
+})
+export class InfoBannerTitleComponent {
+}
+
+@Component({
+ selector: 'info-banner-content',
+ template: `
+
+
+
+ `,
+ styleUrls: ['info-banner.component.sass']
+})
+export class InfoBannerContentComponent {
+}
+
+@Component({
+ selector: 'info-banner-section',
+ template: `
+
+
+
+ `,
+ styleUrls: ['info-banner.component.sass']
+})
+export class InfoBannerSectionComponent {
+}
diff --git a/src/app/modules/shared/components/info-banner/info-banner.module.ts b/src/app/modules/shared/components/info-banner/info-banner.module.ts
new file mode 100644
index 0000000..4afef82
--- /dev/null
+++ b/src/app/modules/shared/components/info-banner/info-banner.module.ts
@@ -0,0 +1,24 @@
+import {NgModule} from '@angular/core'
+import {
+ InfoBannerComponent,
+ InfoBannerContentComponent,
+ InfoBannerSectionComponent,
+ InfoBannerTitleComponent
+} from './info-banner.component'
+
+@NgModule({
+ declarations: [
+ InfoBannerComponent,
+ InfoBannerTitleComponent,
+ InfoBannerContentComponent,
+ InfoBannerSectionComponent
+ ],
+ exports: [
+ InfoBannerComponent,
+ InfoBannerTitleComponent,
+ InfoBannerContentComponent,
+ InfoBannerSectionComponent
+ ]
+})
+export class InfoBannerModule {
+}
diff --git a/src/app/modules/shared/components/inputs/autocomplete-input.html b/src/app/modules/shared/components/inputs/autocomplete-input.html
new file mode 100644
index 0000000..bc21b24
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/autocomplete-input.html
@@ -0,0 +1,31 @@
+
+ {{label}}
+
+
+
+
+ Ce champ est requis
+
+
+
+
+ {{option}}
+
+
+
diff --git a/src/app/modules/shared/components/inputs/chip-combo-box.html b/src/app/modules/shared/components/inputs/chip-combo-box.html
new file mode 100644
index 0000000..443ff0c
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/chip-combo-box.html
@@ -0,0 +1,37 @@
+
+ {{label}}
+
+
+ {{value}}
+ cancel
+
+
+
+
+
+
+
+ Ce champ est requis
+
+
+
+
+
+ {{option.display ? option.display : option.value}}
+
+
+
diff --git a/src/app/modules/shared/components/inputs/chip-input.html b/src/app/modules/shared/components/inputs/chip-input.html
new file mode 100644
index 0000000..4faf8f5
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/chip-input.html
@@ -0,0 +1,23 @@
+
+ {{label}}
+
+
+ {{value}}
+ cancel
+
+
+
+
+
diff --git a/src/app/modules/shared/components/inputs/combo-box.html b/src/app/modules/shared/components/inputs/combo-box.html
new file mode 100644
index 0000000..5170f8c
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/combo-box.html
@@ -0,0 +1,22 @@
+
+ {{label}}
+
+
+
+
+ Ce champ est requis
+
+
+
+
+
+ {{option.value}}
+
+
+
diff --git a/src/app/modules/shared/components/inputs/input.html b/src/app/modules/shared/components/inputs/input.html
new file mode 100644
index 0000000..d7ef1cd
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/input.html
@@ -0,0 +1,28 @@
+
+ {{label}}
+
+
+
+
+ Ce champ est requis
+
+
+
diff --git a/src/app/modules/shared/components/inputs/inputs.module.ts b/src/app/modules/shared/components/inputs/inputs.module.ts
new file mode 100644
index 0000000..d28ce15
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/inputs.module.ts
@@ -0,0 +1,46 @@
+import {NgModule} from '@angular/core'
+import {
+ CreAutocompleteInputComponent,
+ CreChipComboBoxComponent,
+ CreChipInputComponent,
+ CreComboBoxComponent,
+ CreInputComponent
+} from './inputs'
+import {MatInputModule} from '@angular/material/input'
+import {MatIconModule} from '@angular/material/icon'
+import {FormsModule, ReactiveFormsModule} from '@angular/forms'
+import {CommonModule} from '@angular/common'
+import {MatCardModule} from '@angular/material/card'
+import {MatListModule} from '@angular/material/list'
+import {MatAutocompleteModule} from '@angular/material/autocomplete'
+import {MatChipsModule} from '@angular/material/chips'
+
+@NgModule({
+ declarations: [
+ CreInputComponent,
+ CreChipInputComponent,
+ CreAutocompleteInputComponent,
+ CreComboBoxComponent,
+ CreChipComboBoxComponent
+ ],
+ imports: [
+ MatInputModule,
+ MatAutocompleteModule,
+ MatIconModule,
+ ReactiveFormsModule,
+ CommonModule,
+ MatCardModule,
+ MatListModule,
+ MatChipsModule,
+ FormsModule,
+ ],
+ exports: [
+ CreInputComponent,
+ CreComboBoxComponent,
+ CreChipComboBoxComponent,
+ CreChipInputComponent,
+ CreAutocompleteInputComponent
+ ]
+})
+export class CreInputsModule {
+}
diff --git a/src/app/modules/shared/components/inputs/inputs.ts b/src/app/modules/shared/components/inputs/inputs.ts
new file mode 100644
index 0000000..1a64d73
--- /dev/null
+++ b/src/app/modules/shared/components/inputs/inputs.ts
@@ -0,0 +1,190 @@
+import {
+ Component,
+ ContentChild,
+ ElementRef,
+ EventEmitter,
+ Input,
+ OnDestroy,
+ OnInit,
+ Output,
+ TemplateRef,
+ ViewChild,
+ ViewEncapsulation
+} from '@angular/core'
+import {AbstractControl, FormControl, ValidationErrors, ValidatorFn} from '@angular/forms'
+import {COMMA, ENTER} from '@angular/cdk/keycodes'
+import {Observable, Subject} from 'rxjs'
+import {map, takeUntil} from 'rxjs/operators'
+import {MatChipInputEvent} from '@angular/material/chips'
+import {MatAutocomplete, MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'
+
+@Component({
+ selector: 'cre-input',
+ templateUrl: 'input.html',
+ encapsulation: ViewEncapsulation.None
+})
+export class CreInputComponent {
+ @Input() control: FormControl | null
+ @Input() type = 'text'
+ @Input() label: string
+ @Input() icon: string
+ @Input() required = true
+ @Input() autocomplete = true
+ @Input() placeholder: string | null
+ @Input() step = 1
+ @Input() value
+
+ @Output() valueChange = new EventEmitter()
+
+ @ContentChild(TemplateRef) errors: TemplateRef
+}
+
+@Component({
+ selector: 'cre-autocomplete-input',
+ templateUrl: 'autocomplete-input.html',
+ encapsulation: ViewEncapsulation.None
+})
+export class CreAutocompleteInputComponent {
+ @Input() control: FormControl | null
+ @Input() label: string
+ @Input() icon: string
+ @Input() required = true
+ @Input() options: Observable
+ @Input() value
+
+ @Output() valueChange = new EventEmitter()
+
+ @ContentChild(TemplateRef) errors: TemplateRef
+}
+
+@Component({
+ selector: 'cre-chip-input',
+ templateUrl: 'chip-input.html',
+ encapsulation: ViewEncapsulation.None
+})
+export class CreChipInputComponent implements OnInit {
+ @Input() control: FormControl
+ @Input() label: string
+ @Input() icon: string
+ @Input() required = true
+
+ inputControl = new FormControl()
+
+ readonly separatorKeysCodes = [ENTER, COMMA]
+
+ selectedValues = []
+
+ ngOnInit(): void {
+ if (this.control.value) {
+ this.selectedValues = this.control.value
+ }
+ }
+
+ add(event: MatChipInputEvent): void {
+ const input = event.input
+ const value = event.value
+
+ if ((value || '').trim()) {
+ this.selectedValues.push(value.trim())
+ }
+
+ if (input) {
+ input.value = ''
+ }
+
+ this.inputControl.setValue(null)
+ this.control.setValue(this.selectedValues)
+ }
+
+ remove(value): void {
+ const index = this.selectedValues.indexOf(value)
+
+ if (index >= 0) {
+ this.selectedValues.splice(index, 1)
+ this.control.setValue(this.selectedValues)
+ }
+ }
+}
+
+@Component({
+ selector: 'cre-combo-box',
+ templateUrl: 'combo-box.html',
+ encapsulation: ViewEncapsulation.None
+})
+export class CreComboBoxComponent {
+ @Input() control: FormControl
+ @Input() label: string
+ @Input() icon: string
+ @Input() required = true
+ @Input() options: Observable
+
+ @ContentChild(TemplateRef) errors: TemplateRef
+}
+
+@Component({
+ selector: 'cre-chip-combo-box',
+ templateUrl: 'chip-combo-box.html',
+ encapsulation: ViewEncapsulation.None
+})
+export class CreChipComboBoxComponent extends CreChipInputComponent implements OnDestroy {
+ @Input() options: Observable
+
+ @ContentChild(TemplateRef) errors: TemplateRef
+ @ViewChild('chipInput') chipInput: ElementRef
+ @ViewChild('auto') matAutocomplete: MatAutocomplete
+
+ filteredOptions: Observable
+
+ private _options: ComboBoxEntry[]
+ private _destroy$ = new Subject()
+
+ ngOnInit() {
+ super.ngOnInit()
+
+ this.options.pipe(takeUntil(this._destroy$))
+ .subscribe({next: options => this._options = options})
+
+ this.filteredOptions = this.inputControl.valueChanges.pipe(
+ map((query: string | null) => query ? this._filter(query) : this._options.slice())
+ )
+ }
+
+ ngOnDestroy(): void {
+ this._destroy$.complete()
+ }
+
+ selected(event: MatAutocompleteSelectedEvent) {
+ this.selectedValues.push(this.findValueByKey(event.option.value))
+ this.chipInput.nativeElement.value = ''
+ this.inputControl.setValue(null)
+ this.control.setValue(this.selectedValues)
+ }
+
+ get empty(): boolean {
+ return this.selectedValues.length <= 0
+ }
+
+ private _filter(query: string): ComboBoxEntry[] {
+ const filterValue = query.toString().toLowerCase()
+ return this._options.filter(option => option.value.toString().toLowerCase().indexOf(filterValue) === 0)
+ }
+
+ private findValueByKey(key: any): any {
+ return this._options.filter(o => o.key === key)[0].value
+ }
+}
+
+export class ComboBoxEntry {
+ constructor(
+ public key: any,
+ public value: any,
+ public display?: any
+ ) {
+ }
+}
+
+export function chipListRequired(): ValidatorFn {
+ return (control: AbstractControl): ValidationErrors | null => {
+ return !control.value || control.value.length <= 0 ? {required: true} : null
+ }
+}
diff --git a/src/app/modules/shared/components/nav/nav.component.sass b/src/app/modules/shared/components/nav/nav.component.sass
index 05f5622..26455a3 100644
--- a/src/app/modules/shared/components/nav/nav.component.sass
+++ b/src/app/modules/shared/components/nav/nav.component.sass
@@ -3,7 +3,6 @@
nav
position: relative
z-index: 90
- padding-bottom: 1px
a
opacity: 1
diff --git a/src/app/modules/shared/components/tables/table.html b/src/app/modules/shared/components/tables/table.html
new file mode 100644
index 0000000..46560ec
--- /dev/null
+++ b/src/app/modules/shared/components/tables/table.html
@@ -0,0 +1,12 @@
+
diff --git a/src/app/modules/shared/components/tables/table.sass b/src/app/modules/shared/components/tables/table.sass
new file mode 100644
index 0000000..4458b6e
--- /dev/null
+++ b/src/app/modules/shared/components/tables/table.sass
@@ -0,0 +1,12 @@
+@import "~src/custom-theme"
+
+cre-table
+ display: block
+ width: max-content
+
+ tr
+ &:hover
+ background-color: darken(white, 5%)
+
+ &.cre-row-selected
+ background-color: darken(white, 10%)
diff --git a/src/app/modules/shared/components/tables/tables.module.ts b/src/app/modules/shared/components/tables/tables.module.ts
new file mode 100644
index 0000000..2e9576d
--- /dev/null
+++ b/src/app/modules/shared/components/tables/tables.module.ts
@@ -0,0 +1,21 @@
+import {NgModule} from '@angular/core'
+import {MatTableModule} from '@angular/material/table'
+import {CommonModule} from '@angular/common'
+import {CreInteractiveCell, CreTable} from './tables'
+
+@NgModule({
+ declarations: [
+ CreTable,
+ CreInteractiveCell
+ ],
+ imports: [
+ MatTableModule,
+ CommonModule
+ ],
+ exports: [
+ CreTable,
+ CreInteractiveCell,
+ ]
+})
+export class CreTablesModule {
+}
diff --git a/src/app/modules/shared/components/tables/tables.ts b/src/app/modules/shared/components/tables/tables.ts
new file mode 100644
index 0000000..59cec5c
--- /dev/null
+++ b/src/app/modules/shared/components/tables/tables.ts
@@ -0,0 +1,83 @@
+import {
+ AfterContentInit,
+ Component,
+ ContentChildren,
+ Directive,
+ HostBinding,
+ Input,
+ QueryList,
+ ViewChild,
+ ViewEncapsulation
+} from '@angular/core'
+import {MatColumnDef, MatHeaderRowDef, MatRowDef, MatTable} from '@angular/material/table'
+
+@Directive({
+ selector: '[creInteractiveCell]'
+})
+export class CreInteractiveCell implements AfterContentInit {
+ @Input('creInteractiveCell') index: number
+
+ @HostBinding() hidden = true
+
+ private _selectedIndex = 0
+ private _hoverIndex = 0
+
+ ngAfterContentInit(): void {
+ this.hidden = this.isHidden
+ }
+
+ set hoverIndex(index: number) {
+ this._hoverIndex = index
+ this.hidden = this.isHidden
+ }
+
+ set selectedIndex(index: number) {
+ this._selectedIndex = index
+ this.hidden = this.isHidden
+ }
+
+ get isHidden(): boolean {
+ return this._hoverIndex !== this.index && this._selectedIndex !== this.index
+ }
+}
+
+@Component({
+ selector: 'cre-table',
+ templateUrl: 'table.html',
+ styleUrls: ['table.sass'],
+ encapsulation: ViewEncapsulation.None
+})
+export class CreTable implements AfterContentInit {
+ @ContentChildren(MatHeaderRowDef) headerRowDefs: QueryList
+ @ContentChildren(MatRowDef) rowDefs: QueryList>
+ @ContentChildren(MatColumnDef) columnDefs: QueryList
+
+ @ContentChildren(CreInteractiveCell, {descendants: true}) interactiveCells: QueryList
+
+ @ViewChild(MatTable, {static: true}) table: MatTable
+
+ @Input() columns: string[]
+ @Input() dataSource: T[]
+ @Input() interactive = true
+
+ selectedIndex = 0
+
+ ngAfterContentInit(): void {
+ this.columnDefs.forEach(columnDef => this.table.addColumnDef(columnDef))
+ this.rowDefs.forEach(rowDef => this.table.addRowDef(rowDef))
+ this.headerRowDefs.forEach(headerRowDef => this.table.addHeaderRowDef(headerRowDef))
+ }
+
+ onRowHover(index: number) {
+ if (this.interactive) {
+ this.interactiveCells.forEach(cell => cell.hoverIndex = index)
+ }
+ }
+
+ onRowSelected(index: number) {
+ if (this.interactive) {
+ this.selectedIndex = index
+ this.interactiveCells.forEach(cell => cell.selectedIndex = index)
+ }
+ }
+}
diff --git a/src/app/modules/shared/directives/var.directive.ts b/src/app/modules/shared/directives/var.directive.ts
new file mode 100644
index 0000000..9aad369
--- /dev/null
+++ b/src/app/modules/shared/directives/var.directive.ts
@@ -0,0 +1,25 @@
+import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core'
+
+@Directive({
+ selector: '[ngVar]'
+})
+export class VarDirective {
+ context: any = {}
+
+ constructor(
+ private vcRef: ViewContainerRef,
+ private templateRef: TemplateRef
+ ) {
+ }
+
+ @Input()
+ set ngVar(context: any) {
+ this.context.$implicit = this.context.ngVar = context
+ this.updateView()
+ }
+
+ private updateView() {
+ this.vcRef.clear()
+ this.vcRef.createEmbeddedView(this.templateRef, this.context)
+ }
+}
diff --git a/src/app/modules/shared/model/recipe.model.ts b/src/app/modules/shared/model/recipe.model.ts
index f48ec29..b1137c4 100644
--- a/src/app/modules/shared/model/recipe.model.ts
+++ b/src/app/modules/shared/model/recipe.model.ts
@@ -11,7 +11,7 @@ export class Recipe {
public color: string,
public gloss: number,
public sample: number,
- public approbationDate: LocalDate,
+ public approbationDate: string,
public remark: string,
public company: Company,
public mixes: Mix[],
diff --git a/src/app/modules/shared/model/touch-up-kit.model.ts b/src/app/modules/shared/model/touch-up-kit.model.ts
new file mode 100644
index 0000000..df625e5
--- /dev/null
+++ b/src/app/modules/shared/model/touch-up-kit.model.ts
@@ -0,0 +1,24 @@
+export class TouchUpKit {
+ constructor(
+ public id: number,
+ public project: string,
+ public buggy: string,
+ public company: string,
+ public quantity: number,
+ public shippingDate: string,
+ public finish: string[],
+ public material: string[],
+ public content: TouchUpKitProduct[]
+ ) {
+ }
+}
+
+export class TouchUpKitProduct {
+ constructor(
+ public id: number,
+ public name: string,
+ public description: string | null,
+ public quantity: number
+ ) {
+ }
+}
diff --git a/src/app/modules/shared/shared.module.ts b/src/app/modules/shared/shared.module.ts
index b1391c7..1d7d62e 100644
--- a/src/app/modules/shared/shared.module.ts
+++ b/src/app/modules/shared/shared.module.ts
@@ -32,10 +32,13 @@ import {MatSliderModule} from '@angular/material/slider'
import {SliderFieldComponent} from './components/slider-field/slider-field.component'
import {LoadingWheelComponent} from './components/loading-wheel/loading-wheel.component'
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'
-
+import {InfoBannerModule} from './components/info-banner/info-banner.module'
+import {CreFormsModule} from './components/forms/forms.module'
+import {VarDirective} from './directives/var.directive'
+import {CreColorPreview} from './components/color-preview/color-preview'
@NgModule({
- declarations: [HeaderComponent, UserMenuComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent, FileButtonComponent, GlobalAlertHandlerComponent, SliderFieldComponent, LoadingWheelComponent],
+ declarations: [VarDirective, HeaderComponent, UserMenuComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent, FileButtonComponent, GlobalAlertHandlerComponent, SliderFieldComponent, LoadingWheelComponent, CreColorPreview],
exports: [
CommonModule,
HttpClientModule,
@@ -64,7 +67,11 @@ import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'
FileButtonComponent,
GlobalAlertHandlerComponent,
LoadingWheelComponent,
- RouterModule
+ RouterModule,
+ InfoBannerModule,
+ CreFormsModule,
+ VarDirective,
+ CreColorPreview
],
imports: [
MatTabsModule,
diff --git a/src/app/modules/shared/utils/utils.ts b/src/app/modules/shared/utils/utils.ts
index 266f1e1..e9eaab1 100644
--- a/src/app/modules/shared/utils/utils.ts
+++ b/src/app/modules/shared/utils/utils.ts
@@ -1,4 +1,8 @@
/** Returns [value] if it is not null or [or]. */
+import {DateTimeFormatter, LocalDate} from 'js-joda'
+import {TouchUpKit} from '../model/touch-up-kit.model'
+import {environment} from '../../../../environments/environment'
+
export function valueOr(value: T, or: T): T {
return value ? value : or
}
@@ -14,7 +18,27 @@ export function openJpg(url: string) {
openUrl(url, MEDIA_TYPE_JPG)
}
-function openUrl(url: string, mediaType: string) {
- const encodedUrl = `${url}&mediaType=${encodeURIComponent(mediaType)}`
- window.open(encodedUrl, '_blank')
+export function openTouchUpKit(touchUpKit: TouchUpKit) {
+ openRawUrl(`${environment.apiUrl}/touchupkit/pdf?project=${touchUpKit.project}`)
+}
+
+export function openUrl(url: string, mediaType: string) {
+ openRawUrl(`${url}&mediaType=${encodeURIComponent(mediaType)}`)
+}
+
+export function openRawUrl(url: string) {
+ window.open(url, '_blank')
+}
+
+const dateFormatter = DateTimeFormatter
+ .ofPattern('dd-MM-yyyy')
+
+export function formatDate(date: string): string {
+ return LocalDate.parse(date).format(dateFormatter)
+}
+
+export function reduceDashes(arr: string[]): string {
+ return arr.reduce((acc, cur) => {
+ return `${acc} - ${cur}`
+ })
}
diff --git a/src/app/modules/touch-up-kit/components/finish.html b/src/app/modules/touch-up-kit/components/finish.html
new file mode 100644
index 0000000..18e7dbd
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/finish.html
@@ -0,0 +1,11 @@
+
+
{{finish}}
+
+
+
+ {{recipe.name}} - {{recipe.company.name}}
+
+
+
+
+
diff --git a/src/app/modules/touch-up-kit/components/finish.sass b/src/app/modules/touch-up-kit/components/finish.sass
new file mode 100644
index 0000000..899e060
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/finish.sass
@@ -0,0 +1,28 @@
+@import '~src/custom-theme'
+
+.touchupkit-finish-container
+ display: inline-block
+ position: relative
+
+.matching
+ text-decoration: underline
+
+.matching-recipes
+ position: absolute
+ top: 1.5em
+ transform: translateX(-25%)
+ width: max-content
+ display: inline-block
+ background-color: white
+ color: $dark-primary-text
+ border-radius: 4px
+
+mat-list
+ padding-top: 0
+
+mat-list-item:hover
+ background-color: darken(white, 5%)
+ cursor: pointer
+
+cre-color-preview
+ display: inline-block
diff --git a/src/app/modules/touch-up-kit/components/finish.ts b/src/app/modules/touch-up-kit/components/finish.ts
new file mode 100644
index 0000000..d91f01b
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/finish.ts
@@ -0,0 +1,42 @@
+import {Component, Input} from '@angular/core'
+import {SubscribingComponent} from '../../shared/components/subscribing.component'
+import {RecipeService} from '../../colors/services/recipe.service'
+import {ErrorService} from '../../shared/service/error.service'
+import {ActivatedRoute, Router} from '@angular/router'
+import {Recipe} from '../../shared/model/recipe.model'
+
+@Component({
+ selector: 'touchupkit-finish',
+ templateUrl: 'finish.html',
+ styleUrls: ['finish.sass']
+})
+export class TouchUpKitFinish extends SubscribingComponent {
+ @Input() finish: string
+
+ hover = false
+ matchesRecipes = false
+ matchingRecipes: Recipe[] | null
+
+ constructor(
+ private recipeService: RecipeService,
+ errorService: ErrorService,
+ router: Router,
+ activatedRoute: ActivatedRoute
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ ngOnInit(): void {
+ this.subscribe(
+ this.recipeService.getAllByName(this.finish),
+ recipes => {
+ this.matchesRecipes = recipes.length > 0
+ this.matchingRecipes = recipes
+ }
+ )
+ }
+
+ openRecipe(recipe: Recipe) {
+ window.open(`/color/explore/${recipe.id}`, '_blank')
+ }
+}
diff --git a/src/app/modules/touch-up-kit/components/form.html b/src/app/modules/touch-up-kit/components/form.html
new file mode 100644
index 0000000..999b820
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/form.html
@@ -0,0 +1,34 @@
+
+ Ajouter un kit de retouche
+
+
+
+
+
+
+
+ La quantité doit être supérieure ou égale à 1
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/touch-up-kit/components/form.ts b/src/app/modules/touch-up-kit/components/form.ts
new file mode 100644
index 0000000..6340f72
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/form.ts
@@ -0,0 +1,92 @@
+import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'
+import {chipListRequired, ComboBoxEntry, CreChipComboBoxComponent} from '../../shared/components/inputs/inputs'
+import {CreFormComponent} from '../../shared/components/forms/forms'
+import {TouchUpKitProductEditor} from './product-editor'
+import {FormControl, Validators} from '@angular/forms'
+import {RecipeService} from '../../colors/services/recipe.service'
+import {CompanyService} from '../../company/service/company.service'
+import {ErrorService} from '../../shared/service/error.service'
+import {ActivatedRoute, Router} from '@angular/router'
+import {TouchUpKit, TouchUpKitProduct} from '../../shared/model/touch-up-kit.model'
+import {SubscribingComponent} from '../../shared/components/subscribing.component'
+import {map} from 'rxjs/operators'
+
+@Component({
+ selector: 'touchupkit-form',
+ templateUrl: 'form.html'
+})
+export class TouchUpKitForm extends SubscribingComponent {
+ @ViewChild('finishInput') finishInput: CreChipComboBoxComponent
+ @ViewChild('materialInput') materialInput: CreChipComboBoxComponent
+ @ViewChild(CreFormComponent) form: CreFormComponent
+ @ViewChild(TouchUpKitProductEditor) contentEditor: TouchUpKitProductEditor
+
+ @Input() touchUpKit: TouchUpKit | null
+
+ controls: any
+ finish$ = this.recipeService.all.pipe(
+ map(recipes => recipes.map(recipe => new ComboBoxEntry(recipe.id, recipe.name, `${recipe.name} - ${recipe.company.name}`)))
+ )
+ companies$ = this.companyService.all.pipe(
+ map(companies => companies.map(company => company.name))
+ )
+
+ @Output() submitForm = new EventEmitter()
+
+ constructor(
+ private recipeService: RecipeService,
+ private companyService: CompanyService,
+ errorService: ErrorService,
+ activatedRoute: ActivatedRoute,
+ router: Router,
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ ngOnInit() {
+ super.ngOnInit()
+
+ this.controls = {
+ project: new FormControl(this.touchUpKit?.project, Validators.required),
+ buggy: new FormControl(this.touchUpKit?.buggy, Validators.required),
+ company: new FormControl(this.touchUpKit?.company, Validators.required),
+ quantity: new FormControl(this.touchUpKit?.quantity, Validators.compose([Validators.required, Validators.min(1)])),
+ shippingDate: new FormControl(this.touchUpKit?.shippingDate, Validators.required),
+ finish: new FormControl(this.touchUpKit?.finish, chipListRequired()),
+ material: new FormControl(this.touchUpKit?.material, chipListRequired())
+ }
+ }
+
+ submit() {
+ this.submitForm.emit({
+ id: this.touchUpKit ? this.touchUpKit.id : null,
+ project: this.controls.project.value,
+ buggy: this.controls.buggy.value,
+ company: this.controls.company.value,
+ quantity: this.controls.quantity.value,
+ shippingDate: this.controls.shippingDate.value,
+ finish: this.selectedFinish,
+ material: this.selectedMaterial,
+ content: this.touchUpKitContent
+ })
+ }
+
+ get selectedFinish(): string[] {
+ return this.finishInput.selectedValues
+ }
+
+ get selectedMaterial(): string[] {
+ return this.materialInput.selectedValues
+ }
+
+ get touchUpKitContent(): TouchUpKitProduct[] {
+ return this.contentEditor.products
+ }
+
+ get formValid(): boolean {
+ return this.form && !this.form.invalid &&
+ !this.finishInput.empty &&
+ !this.materialInput.empty &&
+ !this.contentEditor.empty
+ }
+}
diff --git a/src/app/modules/touch-up-kit/components/product-editor.html b/src/app/modules/touch-up-kit/components/product-editor.html
new file mode 100644
index 0000000..477335b
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/product-editor.html
@@ -0,0 +1,55 @@
+
+
+ Contenu
+
+
+
+
+ Nom |
+
+
+
+ {{product.name}}
+
+ |
+
+
+
+ Description |
+
+
+
+ {{product.description ? product.description : '-'}}
+
+ |
+
+
+
+ Quantité |
+
+
+
+ {{product.quantity}}
+
+ |
+
+
+
+
+ Ajouter
+ |
+
+ Retirer
+ |
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/touch-up-kit/components/product-editor.sass b/src/app/modules/touch-up-kit/components/product-editor.sass
new file mode 100644
index 0000000..eaad423
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/product-editor.sass
@@ -0,0 +1,25 @@
+@import '../../../../custom-theme'
+
+touchupkit-product-editor
+ .mat-form-field-label-wrapper
+ opacity: 0
+
+ cre-input, span.focused
+ display: inline-block
+ width: 15rem
+
+ span.focused
+ white-space: nowrap
+ overflow: hidden
+
+ // Content card
+ mat-card-content
+ margin: 0
+ padding: 0
+
+ table
+ border: none
+ box-shadow: none
+
+ th
+ border-radius: 0 !important
diff --git a/src/app/modules/touch-up-kit/components/product-editor.ts b/src/app/modules/touch-up-kit/components/product-editor.ts
new file mode 100644
index 0000000..ea2d840
--- /dev/null
+++ b/src/app/modules/touch-up-kit/components/product-editor.ts
@@ -0,0 +1,57 @@
+import {Component, Input, OnInit, ViewChild, ViewEncapsulation} from '@angular/core'
+import {TouchUpKitProduct} from '../../shared/model/touch-up-kit.model'
+import {MatTable} from '@angular/material/table'
+
+@Component({
+ selector: 'touchupkit-product-editor',
+ templateUrl: 'product-editor.html',
+ styleUrls: ['product-editor.sass'],
+ encapsulation: ViewEncapsulation.None
+})
+export class TouchUpKitProductEditor implements OnInit {
+ productCols = ['name', 'description', 'quantity', 'removeButton']
+
+ @Input() products: TouchUpKitProduct[]
+
+ @ViewChild(MatTable) table: MatTable
+ hoveredProduct: TouchUpKitProduct | null
+ selectedProduct: TouchUpKitProduct | null
+
+ ngOnInit(): void {
+ if (!this.products) {
+ this.products = [this.emptyProduct]
+ }
+ }
+
+ addRow() {
+ const newProduct = this.emptyProduct
+
+ this.products.push(newProduct)
+ this.table.renderRows()
+ this.selectedProduct = newProduct
+ }
+
+ removeRow(product: TouchUpKitProduct) {
+ this.products = this.products.filter(p => p !== product)
+ this.table.renderRows()
+ }
+
+ isFocused(index: number, product: TouchUpKitProduct): boolean {
+ return (!this.hoveredProduct && index === 0) ||
+ this.hoveredProduct === product ||
+ this.selectedProduct === product
+ }
+
+ get empty(): boolean {
+ return this.products.length <= 0
+ }
+
+ get emptyProduct(): TouchUpKitProduct {
+ return {
+ id: null,
+ name: '',
+ description: '',
+ quantity: 1
+ }
+ }
+}
diff --git a/src/app/modules/touch-up-kit/pages/add.html b/src/app/modules/touch-up-kit/pages/add.html
new file mode 100644
index 0000000..be52732
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/add.html
@@ -0,0 +1,11 @@
+
+
+ Retour
+
+
+ Enregistrer
+
+
+
+
+
diff --git a/src/app/modules/touch-up-kit/pages/banner.html b/src/app/modules/touch-up-kit/pages/banner.html
new file mode 100644
index 0000000..4da19bc
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/banner.html
@@ -0,0 +1,19 @@
+
+ {{touchUpKit.project}} - {{touchUpKit.company}}
+
+
+ Chariot: {{touchUpKit.buggy}}
+ Quantité: {{touchUpKit.quantity}}
+ Date de livraison: {{shippingDate}}
+
+
+ Fini:
+
+
+ -
+
+
+ Matériel: {{material}}
+
+
+
diff --git a/src/app/modules/touch-up-kit/pages/details.html b/src/app/modules/touch-up-kit/pages/details.html
new file mode 100644
index 0000000..99bbb6c
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/details.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+ Nom |
+ {{product.name}} |
+
+
+
+ Description |
+
+ {{product.description}}
+ -
+ |
+
+
+
+ Quantité |
+ {{product.quantity}} |
+
+
+
diff --git a/src/app/modules/touch-up-kit/pages/details.sass b/src/app/modules/touch-up-kit/pages/details.sass
new file mode 100644
index 0000000..caf74e0
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/details.sass
@@ -0,0 +1,2 @@
+info-banner-section p
+ margin-bottom: 0
diff --git a/src/app/modules/touch-up-kit/pages/edit.html b/src/app/modules/touch-up-kit/pages/edit.html
new file mode 100644
index 0000000..7fd4938
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/edit.html
@@ -0,0 +1,24 @@
+
+
+
+ Retour
+
+
+ Supprimer
+ Enregistrer
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/touch-up-kit/pages/list.html b/src/app/modules/touch-up-kit/pages/list.html
new file mode 100644
index 0000000..e5fc496
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/list.html
@@ -0,0 +1,53 @@
+
+
+
+ Ajouter
+
+
+
+
+
+ Project |
+ {{touchUpKit.project}} |
+
+
+
+ Chariot |
+ {{touchUpKit.buggy}} |
+
+
+
+ Bannière |
+ {{touchUpKit.company}} |
+
+
+
+ Date de livraison |
+ {{touchUpKit.shippingDate}} |
+
+
+
+ |
+
+ PDF
+ |
+
+
+
+ |
+
+
+ Détails
+
+ |
+
+
+
+ |
+
+
+ Modifier
+
+ |
+
+
diff --git a/src/app/modules/touch-up-kit/pages/touchupkit.ts b/src/app/modules/touch-up-kit/pages/touchupkit.ts
new file mode 100644
index 0000000..a050397
--- /dev/null
+++ b/src/app/modules/touch-up-kit/pages/touchupkit.ts
@@ -0,0 +1,152 @@
+import {Component, Input} from '@angular/core'
+import {TouchUpKit} from '../../shared/model/touch-up-kit.model'
+import {formatDate, openTouchUpKit, reduceDashes} from '../../shared/utils/utils'
+import {ErrorHandlingComponent} from '../../shared/components/subscribing.component'
+import {TouchUpKitService} from '../service/touch-up-kit.service'
+import {AccountService} from '../../accounts/services/account.service'
+import {ErrorService} from '../../shared/service/error.service'
+import {ActivatedRoute, Router} from '@angular/router'
+import {Permission} from '../../shared/model/user'
+import {RecipeService} from '../../colors/services/recipe.service'
+
+@Component({
+ selector: 'touchupkit-banner',
+ templateUrl: 'banner.html',
+ styles: [
+ 'p { margin-bottom: 0 }'
+ ]
+})
+export class TouchUpKitBanner {
+ @Input() touchUpKit: TouchUpKit
+
+ get shippingDate(): string {
+ return formatDate(this.touchUpKit.shippingDate)
+ }
+
+ get material(): string {
+ return reduceDashes(this.touchUpKit.material)
+ }
+}
+
+@Component({
+ selector: 'touchupkit-list',
+ templateUrl: './list.html'
+})
+export class TouchUpKitList extends ErrorHandlingComponent {
+ touchUpKits$ = this.touchUpKitService.all
+ columns = ['project', 'buggy', 'company', 'shippingDate', 'pdfButton', 'detailsButton', 'editButton']
+
+ constructor(
+ private touchUpKitService: TouchUpKitService,
+ private accountService: AccountService,
+ errorService: ErrorService,
+ router: Router,
+ activatedRoute: ActivatedRoute
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ openTouchUpKitPdf(touchUpKit: TouchUpKit) {
+ openTouchUpKit(touchUpKit)
+ }
+
+ get canEditTouchUpKits(): boolean {
+ return this.accountService.hasPermission(Permission.EDIT_TOUCH_UP_KITS)
+ }
+}
+
+@Component({
+ selector: 'touchupkit-details',
+ templateUrl: 'details.html'
+})
+export class TouchUpKitDetails extends ErrorHandlingComponent {
+ touchUpKit: TouchUpKit | null
+ contentTableCols = ['name', 'description', 'quantity']
+
+ constructor(
+ private touchUpKitService: TouchUpKitService,
+ private recipeService: RecipeService,
+ errorService: ErrorService,
+ activatedRoute: ActivatedRoute,
+ router: Router
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ ngOnInit() {
+ super.ngOnInit()
+
+ this.subscribeEntityById(
+ this.touchUpKitService,
+ this.urlUtils.parseIntUrlParam('id'),
+ t => this.touchUpKit = t
+ )
+ }
+
+ openPdf() {
+ openTouchUpKit(this.touchUpKit)
+ }
+}
+
+@Component({
+ selector: 'touchupkit-add',
+ templateUrl: 'add.html'
+})
+export class TouchUpKitAdd extends ErrorHandlingComponent {
+ constructor(
+ private touchUpKitService: TouchUpKitService,
+ errorService: ErrorService,
+ activatedRoute: ActivatedRoute,
+ router: Router,
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ submit(touchUpKit) {
+ this.subscribeAndNavigate(
+ this.touchUpKitService.save(touchUpKit),
+ '/misc/touch-up-kit/list'
+ )
+ }
+}
+
+@Component({
+ selector: 'touchupkit-edit',
+ templateUrl: 'edit.html'
+})
+export class TouchUpKitEdit extends ErrorHandlingComponent {
+ touchUpKit: TouchUpKit | null
+
+ constructor(
+ private touchUpKitService: TouchUpKitService,
+ errorService: ErrorService,
+ activatedRoute: ActivatedRoute,
+ router: Router
+ ) {
+ super(errorService, activatedRoute, router)
+ }
+
+ ngOnInit() {
+ super.ngOnInit()
+
+ this.subscribeEntityById(
+ this.touchUpKitService,
+ this.urlUtils.parseIntUrlParam('id'),
+ touchUpKit => this.touchUpKit = touchUpKit
+ )
+ }
+
+ submit(touchUpKit) {
+ this.subscribeAndNavigate(
+ this.touchUpKitService.update(touchUpKit),
+ '/misc/touch-up-kit/list'
+ )
+ }
+
+ delete() {
+ this.subscribeAndNavigate(
+ this.touchUpKitService.delete(this.touchUpKit.id),
+ '/misc/touch-up-kit/list'
+ )
+ }
+}
diff --git a/src/app/modules/touch-up-kit/service/touch-up-kit.service.ts b/src/app/modules/touch-up-kit/service/touch-up-kit.service.ts
new file mode 100644
index 0000000..18aa7b2
--- /dev/null
+++ b/src/app/modules/touch-up-kit/service/touch-up-kit.service.ts
@@ -0,0 +1,34 @@
+import {Injectable} from '@angular/core'
+import {ApiService} from '../../shared/service/api.service'
+import {Observable} from 'rxjs'
+import {TouchUpKit, TouchUpKitProduct} from '../../shared/model/touch-up-kit.model'
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TouchUpKitService {
+ constructor(
+ private api: ApiService
+ ) {
+ }
+
+ get all(): Observable {
+ return this.api.get('/touchupkit')
+ }
+
+ getById(id: number): Observable {
+ return this.api.get(`/touchupkit/${id}`)
+ }
+
+ save(touchUpKit: TouchUpKit): Observable {
+ return this.api.post('/touchupkit', touchUpKit)
+ }
+
+ update(touchUpKit: TouchUpKit): Observable {
+ return this.api.put('/touchupkit', touchUpKit)
+ }
+
+ delete(id: number): Observable {
+ return this.api.delete(`/touchupkit/${id}`)
+ }
+}
diff --git a/src/app/modules/touch-up-kit/touch-up-kit-routing.module.ts b/src/app/modules/touch-up-kit/touch-up-kit-routing.module.ts
new file mode 100644
index 0000000..ce570bf
--- /dev/null
+++ b/src/app/modules/touch-up-kit/touch-up-kit-routing.module.ts
@@ -0,0 +1,28 @@
+import {NgModule} from '@angular/core'
+import {RouterModule, Routes} from '@angular/router'
+import {TouchUpKitAdd, TouchUpKitDetails, TouchUpKitEdit, TouchUpKitList} from './pages/touchupkit'
+
+const routes: Routes = [{
+ path: 'list',
+ component: TouchUpKitList
+}, {
+ path: 'details/:id',
+ component: TouchUpKitDetails
+}, {
+ path: 'add',
+ component: TouchUpKitAdd
+}, {
+ path: 'edit/:id',
+ component: TouchUpKitEdit
+}, {
+ path: '',
+ pathMatch: 'full',
+ redirectTo: 'list'
+}]
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class TouchUpKitRoutingModule {
+}
diff --git a/src/app/modules/touch-up-kit/touch-up-kit.module.ts b/src/app/modules/touch-up-kit/touch-up-kit.module.ts
new file mode 100644
index 0000000..067f3d4
--- /dev/null
+++ b/src/app/modules/touch-up-kit/touch-up-kit.module.ts
@@ -0,0 +1,41 @@
+import {NgModule} from '@angular/core'
+import {CommonModule} from '@angular/common'
+import {TouchUpKitRoutingModule} from './touch-up-kit-routing.module'
+import {SharedModule} from '../shared/shared.module'
+import {CreInputsModule} from '../shared/components/inputs/inputs.module'
+import {CreButtonsModule} from '../shared/components/buttons/buttons.module'
+import {TouchUpKitProductEditor} from './components/product-editor'
+import {FormsModule} from '@angular/forms'
+import {CreActionBarModule} from '../shared/components/action-bar/action-bar.module'
+import {TouchUpKitForm} from './components/form'
+import {CreTablesModule} from '../shared/components/tables/tables.module'
+import {TouchUpKitAdd, TouchUpKitBanner, TouchUpKitDetails, TouchUpKitEdit, TouchUpKitList} from './pages/touchupkit'
+import {TouchUpKitFinish} from './components/finish'
+import {MatTooltipModule} from '@angular/material/tooltip'
+
+
+@NgModule({
+ declarations: [
+ TouchUpKitForm,
+ TouchUpKitProductEditor,
+ TouchUpKitBanner,
+ TouchUpKitFinish,
+ TouchUpKitList,
+ TouchUpKitDetails,
+ TouchUpKitAdd,
+ TouchUpKitEdit
+ ],
+ imports: [
+ CommonModule,
+ TouchUpKitRoutingModule,
+ SharedModule,
+ CreInputsModule,
+ CreButtonsModule,
+ FormsModule,
+ CreActionBarModule,
+ CreTablesModule,
+ MatTooltipModule
+ ]
+})
+export class TouchUpKitModule {
+}
diff --git a/src/app/pages/others/misc.component.ts b/src/app/pages/others/misc.component.ts
index fe3f2c9..03d63a8 100644
--- a/src/app/pages/others/misc.component.ts
+++ b/src/app/pages/others/misc.component.ts
@@ -10,6 +10,6 @@ import {Permission} from '../../modules/shared/model/user'
})
export class MiscComponent extends SubMenuComponent{
links: NavLink[] = [
- {route: '/misc/touchupkit', title: 'Kits de retouche', permission: Permission.VIEW_TOUCH_UP_KITS}
+ {route: '/misc/touch-up-kit', title: 'Kits de retouche', permission: Permission.VIEW_TOUCH_UP_KITS}
]
}
diff --git a/src/app/pages/others/touchupkit/touchupkit.component.html b/src/app/pages/others/touchupkit/touchupkit.component.html
deleted file mode 100644
index 0218a25..0000000
--- a/src/app/pages/others/touchupkit/touchupkit.component.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- Génération d'un kit de retouche
-
-
-
-
-
-
-
-
diff --git a/src/app/pages/others/touchupkit/touchupkit.component.sass b/src/app/pages/others/touchupkit/touchupkit.component.sass
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/pages/others/touchupkit/touchupkit.component.ts b/src/app/pages/others/touchupkit/touchupkit.component.ts
deleted file mode 100644
index 1ffe1e8..0000000
--- a/src/app/pages/others/touchupkit/touchupkit.component.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import {Component, OnInit} from '@angular/core'
-import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'
-import {TouchupkitService} from '../../../modules/shared/service/touchupkit.service'
-
-@Component({
- selector: 'cre-touchupkit',
- templateUrl: './touchupkit.component.html',
- styleUrls: ['./touchupkit.component.sass']
-})
-export class TouchupkitComponent implements OnInit {
- formGroup: FormGroup
- jobControl: FormControl
-
- constructor(
- private touchUpKitService: TouchupkitService,
- private formBuilder: FormBuilder
- ) {
- }
-
- ngOnInit(): void {
- this.jobControl = new FormControl(null, Validators.required)
- this.formGroup = this.formBuilder.group({
- job: this.jobControl
- })
- }
-
- submit() {
- this.touchUpKitService.generateJobPdfDocument(this.jobControl.value)
- }
-}
diff --git a/src/styles.sass b/src/styles.sass
index 146b03d..5570317 100644
--- a/src/styles.sass
+++ b/src/styles.sass
@@ -5,7 +5,6 @@
mat-card
padding: 0 !important
width: max-content
- max-width: 50rem
&.x-centered
margin: auto
@@ -168,27 +167,6 @@ div.empty
margin-left: 0
margin-right: 1rem
-.recipe-color-circle
- color: black
- width: 2.2rem
- height: 2.2rem
- border-radius: 1.1rem
- margin-left: 1rem
- font-size: 13px
-
- &.dark-mode
- color: white
- width: 2.3rem
- height: 2.3rem
- border: solid 1px white
-
- div
- position: absolute
- width: 2rem
- text-align: center
- margin-top: 7px
- margin-left: 1px
-
.alert p
margin-bottom: 0