@wizco/fenixds-ngx 17.12.1 → 17.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ import * as i1$1 from '@angular/common/http';
6
6
  import { HttpEventType, HttpClientModule } from '@angular/common/http';
7
7
  import * as i1$2 from '@angular/router';
8
8
  import { NavigationEnd, RouterModule } from '@angular/router';
9
+ import * as i2 from '@angular/forms';
9
10
  import { FormControl, NG_VALUE_ACCESSOR, NG_VALIDATORS, ReactiveFormsModule, FormsModule } from '@angular/forms';
10
11
  import * as i1$3 from '@angular/platform-browser';
11
12
 
@@ -3346,6 +3347,348 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3346
3347
  args: ['window:resize']
3347
3348
  }] } });
3348
3349
 
3350
+ class ContractsComponent {
3351
+ elementRef;
3352
+ /**
3353
+ * Contratos já gerados, exibidos na listagem
3354
+ */
3355
+ contracts = [];
3356
+ /**
3357
+ * Templates de documento disponíveis (apenas mapeados e ativos)
3358
+ */
3359
+ templates = [];
3360
+ /**
3361
+ * Participantes disponíveis para assinatura do contrato
3362
+ */
3363
+ signers = [];
3364
+ /**
3365
+ * Papéis padrão, usados quando o template escolhido não traz os seus
3366
+ * próprios em `templates[].roles`
3367
+ */
3368
+ roles = ['Contratante', 'Signatário', 'Testemunha'];
3369
+ /**
3370
+ * Título do card de contratos
3371
+ */
3372
+ title = 'Contratos';
3373
+ /**
3374
+ * Mensagem exibida quando não há contratos gerados
3375
+ */
3376
+ emptyMessage = 'Os contratos estão prontos para serem gerados!';
3377
+ /**
3378
+ * Ícone (material icons) do estado vazio
3379
+ */
3380
+ emptyIcon = 'description';
3381
+ /**
3382
+ * Loading da listagem de contratos
3383
+ */
3384
+ loading = false;
3385
+ /**
3386
+ * Estado da requisição de criação do contrato. Enquanto true, o botão
3387
+ * "Gerar contrato" exibe loading (btn-loading) e o modal permanece
3388
+ * aberto; na transição true → false o modal é fechado
3389
+ */
3390
+ set generating(value) {
3391
+ const finished = this._generating && !value;
3392
+ this._generating = value;
3393
+ if (finished) {
3394
+ this.closeGenerateModal();
3395
+ }
3396
+ }
3397
+ get generating() {
3398
+ return this._generating;
3399
+ }
3400
+ _generating = false;
3401
+ /**
3402
+ * Página atual da listagem (paginação server-side)
3403
+ */
3404
+ page = 1;
3405
+ /**
3406
+ * Total de páginas da listagem; a paginação só é exibida
3407
+ * quando houver mais de uma página
3408
+ */
3409
+ totalPages = 0;
3410
+ /**
3411
+ * Solicitação de criação de contrato: template escolhido e
3412
+ * signatários ativos com seus respectivos papéis
3413
+ */
3414
+ generateContract = new EventEmitter();
3415
+ /**
3416
+ * Solicitação de download do documento de um contrato
3417
+ */
3418
+ downloadDocument = new EventEmitter();
3419
+ /**
3420
+ * Emitido ao abrir o modal "Signatários e status" de um contrato.
3421
+ * Permite ao consumidor carregar os signatários sob demanda pela API
3422
+ */
3423
+ signersRequested = new EventEmitter();
3424
+ /**
3425
+ * Emitido ao trocar de página na listagem; o consumidor deve
3426
+ * recarregar os contratos da página solicitada
3427
+ */
3428
+ pageChange = new EventEmitter();
3429
+ generateModal;
3430
+ signersModal;
3431
+ step = 1;
3432
+ templateControl = new FormControl(null);
3433
+ signersState = [];
3434
+ menuOpen = null;
3435
+ menuPosition = { top: 0, right: 0 };
3436
+ contractDetail = null;
3437
+ headers = [
3438
+ { key: 'template', label: 'Template' },
3439
+ { key: 'date', label: 'Data da geração', template: 'date' },
3440
+ { key: 'status', label: 'Status', template: 'status' },
3441
+ ];
3442
+ get stepTemplateBullet() {
3443
+ return this.step === 1 ? '1' : undefined;
3444
+ }
3445
+ get stepTemplateIcon() {
3446
+ return this.step === 2 ? 'check' : undefined;
3447
+ }
3448
+ get activeSigners() {
3449
+ return this.signersState.filter((signer) => !signer.removed);
3450
+ }
3451
+ get selectedTemplate() {
3452
+ return this.templates.find((template) => template.id === this.templateControl.value);
3453
+ }
3454
+ /**
3455
+ * Papéis exibidos na etapa de signatários: os do template escolhido,
3456
+ * ou o input `roles` quando o template não os define
3457
+ */
3458
+ get availableRoles() {
3459
+ const templateRoles = this.selectedTemplate?.roles;
3460
+ return templateRoles?.length ? templateRoles : this.roles;
3461
+ }
3462
+ constructor(elementRef) {
3463
+ this.elementRef = elementRef;
3464
+ }
3465
+ closeMenu() {
3466
+ this.menuOpen = null;
3467
+ }
3468
+ openGenerateModal() {
3469
+ this.step = 1;
3470
+ this.templateControl.reset();
3471
+ this.signersState = this.signers.map((signer) => ({
3472
+ ...signer,
3473
+ role: '',
3474
+ removed: false,
3475
+ }));
3476
+ this.generateModal?.nativeElement.showModal();
3477
+ }
3478
+ closeGenerateModal() {
3479
+ this.generateModal?.nativeElement.close();
3480
+ }
3481
+ nextStep() {
3482
+ if (this.templateControl.value) {
3483
+ this.step = 2;
3484
+ }
3485
+ }
3486
+ toggleSigner(signer) {
3487
+ signer.removed = !signer.removed;
3488
+ if (signer.removed) {
3489
+ signer.role = '';
3490
+ }
3491
+ }
3492
+ /**
3493
+ * Um papel só pode ser usado por um signatário: já escolhido por
3494
+ * outro signatário ativo, fica desabilitado no select dos demais
3495
+ */
3496
+ isRoleTaken(role, signer) {
3497
+ return this.activeSigners.some((other) => other !== signer && other.role === role);
3498
+ }
3499
+ /**
3500
+ * Signatário ativo sem papel fica desabilitado quando todos os papéis
3501
+ * disponíveis já foram tomados pelos demais; ele sai da validação e do
3502
+ * payload de geração, e volta a habilitar se algum papel for liberado
3503
+ */
3504
+ isSignerBlocked(signer) {
3505
+ return (!signer.removed &&
3506
+ !signer.role &&
3507
+ this.availableRoles.every((role) => this.isRoleTaken(role, signer)));
3508
+ }
3509
+ /**
3510
+ * Só permite gerar o contrato quando todos os signatários ativos e não
3511
+ * bloqueados possuem um papel vinculado
3512
+ */
3513
+ canGenerate() {
3514
+ const eligible = this.activeSigners.filter((signer) => !this.isSignerBlocked(signer));
3515
+ return eligible.length > 0 && eligible.every((signer) => !!signer.role);
3516
+ }
3517
+ generate() {
3518
+ const template = this.selectedTemplate;
3519
+ if (!template || !this.canGenerate() || this.generating) {
3520
+ return;
3521
+ }
3522
+ this.generateContract.emit({
3523
+ template,
3524
+ signers: this.activeSigners
3525
+ .filter((signer) => !this.isSignerBlocked(signer))
3526
+ .map(({ name, email, role }) => ({
3527
+ name,
3528
+ email,
3529
+ role,
3530
+ })),
3531
+ });
3532
+ // Consumidor que seta [generating]="true" no handler mantém o modal
3533
+ // aberto com o botão em loading até a requisição terminar; quem não
3534
+ // usa o input mantém o comportamento de fechar imediatamente
3535
+ setTimeout(() => {
3536
+ if (!this.generating) {
3537
+ this.closeGenerateModal();
3538
+ }
3539
+ });
3540
+ }
3541
+ /**
3542
+ * O menu é renderizado na raiz do componente (fora da área rolável da
3543
+ * tabela) e posicionado de forma absoluta em relação a ela, a partir
3544
+ * da posição do botão que o abriu
3545
+ */
3546
+ toggleMenu(row, event) {
3547
+ event.stopPropagation();
3548
+ if (this.menuOpen === row) {
3549
+ this.menuOpen = null;
3550
+ return;
3551
+ }
3552
+ const button = event.currentTarget;
3553
+ const host = this.elementRef.nativeElement.querySelector('.wco-contracts');
3554
+ const hostRect = (host ?? this.elementRef.nativeElement).getBoundingClientRect();
3555
+ const rect = button.getBoundingClientRect();
3556
+ this.menuPosition = {
3557
+ top: rect.bottom - hostRect.top + 4,
3558
+ right: hostRect.right - rect.right,
3559
+ };
3560
+ this.menuOpen = row;
3561
+ }
3562
+ openSigners(row) {
3563
+ this.menuOpen = null;
3564
+ this.contractDetail = row;
3565
+ this.signersRequested.emit(row);
3566
+ this.signersModal?.nativeElement.showModal();
3567
+ }
3568
+ closeSigners() {
3569
+ this.signersModal?.nativeElement.close();
3570
+ }
3571
+ download(row) {
3572
+ this.menuOpen = null;
3573
+ this.downloadDocument.emit(row);
3574
+ }
3575
+ /**
3576
+ * O wco-pagination pode emitir string (número clicado) ou até '...'
3577
+ * (reticências não desabilitadas de fato); saneia antes de reemitir
3578
+ */
3579
+ onPageChange(value) {
3580
+ const page = Number(value);
3581
+ if (!Number.isFinite(page) || page < 1 || page === this.page) {
3582
+ return;
3583
+ }
3584
+ this.page = page;
3585
+ this.pageChange.emit(page);
3586
+ }
3587
+ /**
3588
+ * Tradução dos status retornados pela API de Assinatura Digital
3589
+ * (em inglês, ex.: Signed/Pending/Generated) para exibição
3590
+ */
3591
+ static STATUS_LABELS = {
3592
+ signed: 'Assinado',
3593
+ assinado: 'Assinado',
3594
+ pending: 'Pendente',
3595
+ pendente: 'Pendente',
3596
+ generated: 'Gerado',
3597
+ gerado: 'Gerado',
3598
+ };
3599
+ /**
3600
+ * Status traduzido do contrato/signatário; status desconhecidos
3601
+ * são exibidos como vieram e ausência de status vale Pendente
3602
+ */
3603
+ statusLabel(status) {
3604
+ if (!status) {
3605
+ return 'Pendente';
3606
+ }
3607
+ const key = String(status).trim().toLowerCase();
3608
+ return ContractsComponent.STATUS_LABELS[key] ?? String(status);
3609
+ }
3610
+ isSignedStatus(status) {
3611
+ return this.statusLabel(status) === 'Assinado';
3612
+ }
3613
+ isSigned(row) {
3614
+ return this.isSignedStatus(row.status);
3615
+ }
3616
+ statusClass(status) {
3617
+ const label = this.statusLabel(status);
3618
+ if (label === 'Assinado') {
3619
+ return 'tag-success';
3620
+ }
3621
+ if (label === 'Pendente') {
3622
+ return 'tag-warning';
3623
+ }
3624
+ return 'tag-info';
3625
+ }
3626
+ displayDate(value, separator = ' ') {
3627
+ const date = value instanceof Date ? value : new Date(value);
3628
+ if (isNaN(date.getTime())) {
3629
+ return String(value);
3630
+ }
3631
+ const pad = (num) => String(num).padStart(2, '0');
3632
+ return `${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${date.getFullYear()}${separator}${pad(date.getHours())}:${pad(date.getMinutes())}`;
3633
+ }
3634
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ContractsComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
3635
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ContractsComponent, isStandalone: true, selector: "wco-contracts", inputs: { contracts: "contracts", templates: "templates", signers: "signers", roles: "roles", title: "title", emptyMessage: "emptyMessage", emptyIcon: "emptyIcon", loading: "loading", generating: "generating", page: "page", totalPages: "totalPages" }, outputs: { generateContract: "generateContract", downloadDocument: "downloadDocument", signersRequested: "signersRequested", pageChange: "pageChange" }, host: { listeners: { "document:click": "closeMenu()", "window:resize": "closeMenu()" } }, viewQueries: [{ propertyName: "generateModal", first: true, predicate: ["generateModal"], descendants: true }, { propertyName: "signersModal", first: true, predicate: ["signersModal"], descendants: true }], ngImport: i0, template: "<div class=\"wco-contracts wco-content\">\n <div class=\"wco-contracts__header\">\n <h5 class=\"display-5 bold\">{{ title }}</h5>\n <button\n *ngIf=\"contracts.length > 0\"\n class=\"wco-btn btn-primary\"\n (click)=\"openGenerateModal()\"\n >\n Gerar contrato\n </button>\n </div>\n\n <!-- Estado vazio -->\n <div\n *ngIf=\"contracts.length === 0 && !loading\"\n class=\"flex flex-col items-center gap-xxxs my-lg\"\n >\n <span class=\"material-icons iconEmpty text-primary-500\">{{\n emptyIcon\n }}</span>\n <p class=\"display-p\">{{ emptyMessage }}</p>\n <button class=\"wco-btn btn-primary mt-nano\" (click)=\"openGenerateModal()\">\n Gerar contratos\n </button>\n </div>\n\n <!-- Listagem de contratos -->\n <div *ngIf=\"contracts.length > 0 || loading\" class=\"mt-sm\">\n <ng-template #dateTpl let-data>\n {{ displayDate(data) }}\n </ng-template>\n\n <ng-template #statusTpl let-data let-row=\"row\">\n <div class=\"flex justify-between gap-xxs\">\n <span class=\"wco-tag\" [class]=\"statusClass(data)\">\n <i *ngIf=\"isSignedStatus(data)\" class=\"material-icons\">check_circle</i>\n {{ statusLabel(data) }}\n </span>\n <div class=\"wco-contracts__menu-wrapper\">\n <button\n class=\"wco-btn btn-primary btn-basic btn-icon btn-sm\"\n aria-label=\"A\u00E7\u00F5es do contrato\"\n (click)=\"toggleMenu(row, $event)\"\n >\n <span class=\"material-icons\">more_vert</span>\n </button>\n </div>\n </div>\n </ng-template>\n\n <wco-table\n [headers]=\"headers\"\n [data]=\"contracts\"\n [loading]=\"loading\"\n [templates]=\"{ date: dateTpl, status: statusTpl }\"\n />\n\n <div *ngIf=\"totalPages > 1\" class=\"flex justify-center mt-xs\">\n <wco-pagination\n [totalPage]=\"totalPages\"\n [currenPage]=\"page\"\n (changePage)=\"onPageChange($event)\"\n />\n </div>\n </div>\n\n <!-- Menu de a\u00E7\u00F5es do contrato: renderizado na raiz do componente para\n n\u00E3o ser cortado pelo overflow da \u00E1rea rol\u00E1vel da tabela -->\n <div\n *ngIf=\"menuOpen as openContract\"\n class=\"wco-contracts__menu\"\n [style.top.px]=\"menuPosition.top\"\n [style.right.px]=\"menuPosition.right\"\n >\n <button\n class=\"wco-contracts__menu-item\"\n (click)=\"openSigners(openContract)\"\n >\n <span class=\"material-icons\">person</span>\n Signat\u00E1rios\n </button>\n <button\n class=\"wco-contracts__menu-item\"\n [disabled]=\"!isSigned(openContract)\"\n (click)=\"download(openContract)\"\n >\n <span class=\"material-icons\">download</span>\n Baixar documento\n </button>\n </div>\n\n <!-- Modal Gerar contratos -->\n <dialog\n #generateModal\n class=\"wco-modal wco-contracts__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <main>\n <div class=\"flex justify-between header-modal\">\n <h2 class=\"display-5 bold\">Gerar contratos</h2>\n <button class=\"wco-btn btn-icon btn-sm\" (click)=\"closeGenerateModal()\">\n <span class=\"material-icons text-neutral-500\">close</span>\n </button>\n </div>\n\n <div class=\"my-xs\">\n <wco-stepper-group [size]=\"'full'\" [current]=\"step\">\n <wco-step\n [isVertical]=\"false\"\n [bulletValue]=\"stepTemplateBullet\"\n [iconName]=\"stepTemplateIcon\"\n [status]=\"step === 1 ? 'current' : 'finalized'\"\n label=\"Template\"\n ></wco-step>\n <wco-step\n [isVertical]=\"false\"\n bulletValue=\"2\"\n [status]=\"step === 2 ? 'current' : 'waiting'\"\n label=\"Signat\u00E1rios\"\n ></wco-step>\n </wco-stepper-group>\n </div>\n\n <!-- Etapa 1: Template -->\n <div *ngIf=\"step === 1\">\n <h3 class=\"display-body bold-600\">Template</h3>\n <p class=\"display-p mt-nano text-neutral-700\">\n Escolha um modelo de documento\n </p>\n\n <div class=\"mt-xxs wco-form-field\">\n <select\n [formControl]=\"templateControl\"\n id=\"wcoContractsTemplate\"\n name=\"wcoContractsTemplate\"\n >\n <option [ngValue]=\"null\" disabled>Selecione</option>\n <option *ngFor=\"let template of templates\" [value]=\"template.id\">\n {{ template.name }}\n </option>\n </select>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button\n class=\"wco-btn btn-primary btn-basic\"\n (click)=\"closeGenerateModal()\"\n >\n Cancelar\n </button>\n <button\n class=\"wco-btn btn-primary\"\n [disabled]=\"!templateControl.value\"\n (click)=\"nextStep()\"\n >\n Pr\u00F3ximo\n <span class=\"material-icons\">arrow_forward</span>\n </button>\n </div>\n </div>\n\n <!-- Etapa 2: Signat\u00E1rios -->\n <div *ngIf=\"step === 2\">\n <h3 class=\"display-body bold-600\">Signat\u00E1rios</h3>\n <p class=\"display-p mt-nano text-neutral-700\">\n Defina os pap\u00E9is de cada participante para garantir que o fluxo de\n assinaturas siga as normas jur\u00EDdicas necess\u00E1rias para este contrato.\n </p>\n\n <div class=\"wco-contracts__signers-header\">\n <span class=\"display-text bold-600\">Assinante</span>\n <span class=\"display-text bold-600\">Papel</span>\n </div>\n\n <div *ngFor=\"let signer of signersState\" class=\"wco-contracts__signer\">\n <div\n class=\"wco-contracts__signer-info\"\n [class.wco-contracts__signer-info--removed]=\"\n signer.removed || isSignerBlocked(signer)\n \"\n >\n <span class=\"display-text bold\">{{ signer.name }}</span>\n <span class=\"display-caption\">{{ signer.email }}</span>\n </div>\n <div class=\"wco-contracts__signer-actions\">\n <div class=\"wco-form-field\">\n <select\n [(ngModel)]=\"signer.role\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"signer.removed || isSignerBlocked(signer)\"\n >\n <option value=\"\" disabled>Selecione</option>\n <option\n *ngFor=\"let role of availableRoles\"\n [value]=\"role\"\n [disabled]=\"isRoleTaken(role, signer)\"\n >\n {{ role }}\n </option>\n </select>\n </div>\n <button\n class=\"wco-btn btn-primary btn-basic btn-icon btn-sm\"\n [attr.aria-label]=\"\n signer.removed ? 'Adicionar signat\u00E1rio' : 'Remover signat\u00E1rio'\n \"\n (click)=\"toggleSigner(signer)\"\n >\n <span class=\"material-icons\">{{\n signer.removed ? \"person_add\" : \"person_remove\"\n }}</span>\n </button>\n </div>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button\n class=\"wco-btn btn-primary btn-basic\"\n (click)=\"closeGenerateModal()\"\n >\n Cancelar\n </button>\n <button\n class=\"wco-btn btn-primary\"\n [class.btn-loading]=\"generating\"\n [disabled]=\"!canGenerate() || generating\"\n (click)=\"generate()\"\n >\n Gerar contrato\n </button>\n </div>\n </div>\n </main>\n </dialog>\n\n <!-- Modal Signat\u00E1rios do contrato -->\n <dialog\n #signersModal\n class=\"wco-modal wco-contracts__modal--signers\"\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <main>\n <div class=\"flex justify-between\">\n <h2 class=\"display-5 bold\">Signat\u00E1rios</h2>\n <button class=\"wco-btn btn-icon btn-sm\" (click)=\"closeSigners()\">\n <span class=\"material-icons text-neutral-500\">close</span>\n </button>\n </div>\n\n <p class=\"display-p mt-nano text-neutral-700\">\n Documento: {{ contractDetail?.fileName || contractDetail?.template }}\n </p>\n\n <div class=\"wco-contracts__signer-cards\">\n <div\n *ngFor=\"let signer of contractDetail?.signers\"\n class=\"wco-contracts__signer-card\"\n >\n <div class=\"wco-contracts__signer-card-row\">\n <div class=\"flex items-center gap-nano\">\n <span class=\"wco-contracts__role-tag\">{{ signer.role }}</span>\n <span class=\"display-text bold-600\">{{ signer.name }}</span>\n </div>\n <span class=\"wco-tag\" [class]=\"statusClass(signer.status)\">\n <i *ngIf=\"isSignedStatus(signer.status)\" class=\"material-icons\">check_circle</i>\n {{ statusLabel(signer.status) }}\n </span>\n </div>\n <div class=\"wco-contracts__signer-card-row\">\n <span class=\"display-caption text-neutral-700\">{{ signer.email }}</span>\n <span\n *ngIf=\"isSignedStatus(signer.status) && signer.signedAt\"\n class=\"display-caption text-neutral-700 flex items-center gap-nano\"\n >\n <i class=\"material-icons\">calendar_today</i>\n {{ displayDate(signer.signedAt, ' - ') }}\n </span>\n </div>\n </div>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button class=\"wco-btn btn-primary btn-basic\" (click)=\"closeSigners()\">\n Fechar\n </button>\n </div>\n </main>\n </dialog>\n</div>\n", styles: [".wco-contracts{display:block;position:relative}.wco-contracts__header{display:flex;align-items:center;justify-content:space-between}.wco-contracts__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:48px 16px;text-align:center}.wco-contracts__empty .material-icons{font-size:56px;color:var(--wco-color-primary-700, #1d4ed8)}.wco-contracts__stepper{display:flex;justify-content:center;margin-top:16px;padding:0 48px}.wco-contracts__modal{--wco-modal-size: 560px}.wco-contracts__modal--signers{--wco-modal-size: 480px}.wco-contracts__select-template{min-height:60px}.wco-contracts__footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:32px}.wco-contracts__signers-header{display:flex;align-items:center;justify-content:space-between;margin-top:24px;padding-bottom:8px}.wco-contracts__signers-header span{padding:0 var(--wco-spacing-xxxs)}.wco-contracts__signers-header span:last-child{min-width:208px}.wco-contracts__signer{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:8px 0;border-bottom:1px solid var(--wco-color-neutral-300, #e5e7eb)}.wco-contracts__signer-info{display:flex;flex-direction:column;padding:var(--wco-spacing-xxxs)}.wco-contracts__signer-info--removed{opacity:.4}.wco-contracts__signer-actions{display:flex;align-items:center;gap:8px;padding:var(--wco-spacing-xxxs)}.wco-contracts__signer-actions .wco-form-field{min-width:160px}.wco-contracts__signer-cards{display:flex;flex-direction:column;gap:12px;margin-top:16px}.wco-contracts__signer-card{padding:12px 16px;border:1px solid var(--wco-color-neutral-300, #e5e7eb);border-radius:8px;background:var(--wco-color-neutral-50, #f9fafb)}.wco-contracts__signer-card-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.wco-contracts__signer-card-row+.wco-contracts__signer-card-row{margin-top:4px}.wco-contracts__signer-card-row .material-icons{font-size:16px}.wco-contracts__role-tag{display:inline-flex;align-items:center;padding:2px 12px;border:1px solid var(--wco-color-neutral-300, #e5e7eb);border-radius:16px;background:var(--wco-color-neutral-100, #f3f4f6);color:var(--wco-color-neutral-900, #111827);font-size:12px;font-weight:600;white-space:nowrap}.wco-contracts__menu-wrapper{display:flex;justify-content:flex-end}.wco-contracts__menu{position:absolute;z-index:10;min-width:230px;padding:4px 0;background:#fff;border-radius:8px;box-shadow:0 4px 16px #00000029}.wco-contracts__menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 16px;border:0;background:none;cursor:pointer;font-size:14px;color:var(--wco-color-neutral-900, #111827)}.wco-contracts__menu-item:hover:not(:disabled){background:var(--wco-color-neutral-50, #f9fafb)}.wco-contracts__menu-item:disabled{opacity:.4;cursor:default}.wco-contracts table td{width:25%}.wco-contracts table td:nth-child(1){width:50%}.wco-contracts .iconEmpty{font-size:61px!important}.wco-contracts .bold-600{font-weight:600!important}.wco-contracts .header-modal{margin-top:-24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: PaginationComponent, selector: "wco-pagination", inputs: ["totalPage", "currenPage", "mode"], outputs: ["changePage"] }, { kind: "component", type: StepComponent, selector: "wco-step", inputs: ["active", "label", "iconName", "bulletValue", "isVertical", "lineStart", "lineEnd", "status", "size", "hasClick"], outputs: ["clicked"] }, { kind: "component", type: StepperGroupComponent, selector: "wco-stepper-group", inputs: ["size", "mode", "orientation", "current"] }, { kind: "component", type: TableComponent, selector: "wco-table", inputs: ["data", "sortedItem", "headers", "loading", "templates"], outputs: ["handlerSortedBy"] }], encapsulation: i0.ViewEncapsulation.None });
3636
+ }
3637
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ContractsComponent, decorators: [{
3638
+ type: Component,
3639
+ args: [{ selector: 'wco-contracts', standalone: true, imports: [
3640
+ CommonModule,
3641
+ FormsModule,
3642
+ ReactiveFormsModule,
3643
+ PaginationComponent,
3644
+ StepComponent,
3645
+ StepperGroupComponent,
3646
+ TableComponent,
3647
+ ], encapsulation: ViewEncapsulation.None, template: "<div class=\"wco-contracts wco-content\">\n <div class=\"wco-contracts__header\">\n <h5 class=\"display-5 bold\">{{ title }}</h5>\n <button\n *ngIf=\"contracts.length > 0\"\n class=\"wco-btn btn-primary\"\n (click)=\"openGenerateModal()\"\n >\n Gerar contrato\n </button>\n </div>\n\n <!-- Estado vazio -->\n <div\n *ngIf=\"contracts.length === 0 && !loading\"\n class=\"flex flex-col items-center gap-xxxs my-lg\"\n >\n <span class=\"material-icons iconEmpty text-primary-500\">{{\n emptyIcon\n }}</span>\n <p class=\"display-p\">{{ emptyMessage }}</p>\n <button class=\"wco-btn btn-primary mt-nano\" (click)=\"openGenerateModal()\">\n Gerar contratos\n </button>\n </div>\n\n <!-- Listagem de contratos -->\n <div *ngIf=\"contracts.length > 0 || loading\" class=\"mt-sm\">\n <ng-template #dateTpl let-data>\n {{ displayDate(data) }}\n </ng-template>\n\n <ng-template #statusTpl let-data let-row=\"row\">\n <div class=\"flex justify-between gap-xxs\">\n <span class=\"wco-tag\" [class]=\"statusClass(data)\">\n <i *ngIf=\"isSignedStatus(data)\" class=\"material-icons\">check_circle</i>\n {{ statusLabel(data) }}\n </span>\n <div class=\"wco-contracts__menu-wrapper\">\n <button\n class=\"wco-btn btn-primary btn-basic btn-icon btn-sm\"\n aria-label=\"A\u00E7\u00F5es do contrato\"\n (click)=\"toggleMenu(row, $event)\"\n >\n <span class=\"material-icons\">more_vert</span>\n </button>\n </div>\n </div>\n </ng-template>\n\n <wco-table\n [headers]=\"headers\"\n [data]=\"contracts\"\n [loading]=\"loading\"\n [templates]=\"{ date: dateTpl, status: statusTpl }\"\n />\n\n <div *ngIf=\"totalPages > 1\" class=\"flex justify-center mt-xs\">\n <wco-pagination\n [totalPage]=\"totalPages\"\n [currenPage]=\"page\"\n (changePage)=\"onPageChange($event)\"\n />\n </div>\n </div>\n\n <!-- Menu de a\u00E7\u00F5es do contrato: renderizado na raiz do componente para\n n\u00E3o ser cortado pelo overflow da \u00E1rea rol\u00E1vel da tabela -->\n <div\n *ngIf=\"menuOpen as openContract\"\n class=\"wco-contracts__menu\"\n [style.top.px]=\"menuPosition.top\"\n [style.right.px]=\"menuPosition.right\"\n >\n <button\n class=\"wco-contracts__menu-item\"\n (click)=\"openSigners(openContract)\"\n >\n <span class=\"material-icons\">person</span>\n Signat\u00E1rios\n </button>\n <button\n class=\"wco-contracts__menu-item\"\n [disabled]=\"!isSigned(openContract)\"\n (click)=\"download(openContract)\"\n >\n <span class=\"material-icons\">download</span>\n Baixar documento\n </button>\n </div>\n\n <!-- Modal Gerar contratos -->\n <dialog\n #generateModal\n class=\"wco-modal wco-contracts__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <main>\n <div class=\"flex justify-between header-modal\">\n <h2 class=\"display-5 bold\">Gerar contratos</h2>\n <button class=\"wco-btn btn-icon btn-sm\" (click)=\"closeGenerateModal()\">\n <span class=\"material-icons text-neutral-500\">close</span>\n </button>\n </div>\n\n <div class=\"my-xs\">\n <wco-stepper-group [size]=\"'full'\" [current]=\"step\">\n <wco-step\n [isVertical]=\"false\"\n [bulletValue]=\"stepTemplateBullet\"\n [iconName]=\"stepTemplateIcon\"\n [status]=\"step === 1 ? 'current' : 'finalized'\"\n label=\"Template\"\n ></wco-step>\n <wco-step\n [isVertical]=\"false\"\n bulletValue=\"2\"\n [status]=\"step === 2 ? 'current' : 'waiting'\"\n label=\"Signat\u00E1rios\"\n ></wco-step>\n </wco-stepper-group>\n </div>\n\n <!-- Etapa 1: Template -->\n <div *ngIf=\"step === 1\">\n <h3 class=\"display-body bold-600\">Template</h3>\n <p class=\"display-p mt-nano text-neutral-700\">\n Escolha um modelo de documento\n </p>\n\n <div class=\"mt-xxs wco-form-field\">\n <select\n [formControl]=\"templateControl\"\n id=\"wcoContractsTemplate\"\n name=\"wcoContractsTemplate\"\n >\n <option [ngValue]=\"null\" disabled>Selecione</option>\n <option *ngFor=\"let template of templates\" [value]=\"template.id\">\n {{ template.name }}\n </option>\n </select>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button\n class=\"wco-btn btn-primary btn-basic\"\n (click)=\"closeGenerateModal()\"\n >\n Cancelar\n </button>\n <button\n class=\"wco-btn btn-primary\"\n [disabled]=\"!templateControl.value\"\n (click)=\"nextStep()\"\n >\n Pr\u00F3ximo\n <span class=\"material-icons\">arrow_forward</span>\n </button>\n </div>\n </div>\n\n <!-- Etapa 2: Signat\u00E1rios -->\n <div *ngIf=\"step === 2\">\n <h3 class=\"display-body bold-600\">Signat\u00E1rios</h3>\n <p class=\"display-p mt-nano text-neutral-700\">\n Defina os pap\u00E9is de cada participante para garantir que o fluxo de\n assinaturas siga as normas jur\u00EDdicas necess\u00E1rias para este contrato.\n </p>\n\n <div class=\"wco-contracts__signers-header\">\n <span class=\"display-text bold-600\">Assinante</span>\n <span class=\"display-text bold-600\">Papel</span>\n </div>\n\n <div *ngFor=\"let signer of signersState\" class=\"wco-contracts__signer\">\n <div\n class=\"wco-contracts__signer-info\"\n [class.wco-contracts__signer-info--removed]=\"\n signer.removed || isSignerBlocked(signer)\n \"\n >\n <span class=\"display-text bold\">{{ signer.name }}</span>\n <span class=\"display-caption\">{{ signer.email }}</span>\n </div>\n <div class=\"wco-contracts__signer-actions\">\n <div class=\"wco-form-field\">\n <select\n [(ngModel)]=\"signer.role\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"signer.removed || isSignerBlocked(signer)\"\n >\n <option value=\"\" disabled>Selecione</option>\n <option\n *ngFor=\"let role of availableRoles\"\n [value]=\"role\"\n [disabled]=\"isRoleTaken(role, signer)\"\n >\n {{ role }}\n </option>\n </select>\n </div>\n <button\n class=\"wco-btn btn-primary btn-basic btn-icon btn-sm\"\n [attr.aria-label]=\"\n signer.removed ? 'Adicionar signat\u00E1rio' : 'Remover signat\u00E1rio'\n \"\n (click)=\"toggleSigner(signer)\"\n >\n <span class=\"material-icons\">{{\n signer.removed ? \"person_add\" : \"person_remove\"\n }}</span>\n </button>\n </div>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button\n class=\"wco-btn btn-primary btn-basic\"\n (click)=\"closeGenerateModal()\"\n >\n Cancelar\n </button>\n <button\n class=\"wco-btn btn-primary\"\n [class.btn-loading]=\"generating\"\n [disabled]=\"!canGenerate() || generating\"\n (click)=\"generate()\"\n >\n Gerar contrato\n </button>\n </div>\n </div>\n </main>\n </dialog>\n\n <!-- Modal Signat\u00E1rios do contrato -->\n <dialog\n #signersModal\n class=\"wco-modal wco-contracts__modal--signers\"\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <main>\n <div class=\"flex justify-between\">\n <h2 class=\"display-5 bold\">Signat\u00E1rios</h2>\n <button class=\"wco-btn btn-icon btn-sm\" (click)=\"closeSigners()\">\n <span class=\"material-icons text-neutral-500\">close</span>\n </button>\n </div>\n\n <p class=\"display-p mt-nano text-neutral-700\">\n Documento: {{ contractDetail?.fileName || contractDetail?.template }}\n </p>\n\n <div class=\"wco-contracts__signer-cards\">\n <div\n *ngFor=\"let signer of contractDetail?.signers\"\n class=\"wco-contracts__signer-card\"\n >\n <div class=\"wco-contracts__signer-card-row\">\n <div class=\"flex items-center gap-nano\">\n <span class=\"wco-contracts__role-tag\">{{ signer.role }}</span>\n <span class=\"display-text bold-600\">{{ signer.name }}</span>\n </div>\n <span class=\"wco-tag\" [class]=\"statusClass(signer.status)\">\n <i *ngIf=\"isSignedStatus(signer.status)\" class=\"material-icons\">check_circle</i>\n {{ statusLabel(signer.status) }}\n </span>\n </div>\n <div class=\"wco-contracts__signer-card-row\">\n <span class=\"display-caption text-neutral-700\">{{ signer.email }}</span>\n <span\n *ngIf=\"isSignedStatus(signer.status) && signer.signedAt\"\n class=\"display-caption text-neutral-700 flex items-center gap-nano\"\n >\n <i class=\"material-icons\">calendar_today</i>\n {{ displayDate(signer.signedAt, ' - ') }}\n </span>\n </div>\n </div>\n </div>\n\n <div class=\"wco-contracts__footer\">\n <button class=\"wco-btn btn-primary btn-basic\" (click)=\"closeSigners()\">\n Fechar\n </button>\n </div>\n </main>\n </dialog>\n</div>\n", styles: [".wco-contracts{display:block;position:relative}.wco-contracts__header{display:flex;align-items:center;justify-content:space-between}.wco-contracts__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:48px 16px;text-align:center}.wco-contracts__empty .material-icons{font-size:56px;color:var(--wco-color-primary-700, #1d4ed8)}.wco-contracts__stepper{display:flex;justify-content:center;margin-top:16px;padding:0 48px}.wco-contracts__modal{--wco-modal-size: 560px}.wco-contracts__modal--signers{--wco-modal-size: 480px}.wco-contracts__select-template{min-height:60px}.wco-contracts__footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:32px}.wco-contracts__signers-header{display:flex;align-items:center;justify-content:space-between;margin-top:24px;padding-bottom:8px}.wco-contracts__signers-header span{padding:0 var(--wco-spacing-xxxs)}.wco-contracts__signers-header span:last-child{min-width:208px}.wco-contracts__signer{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:8px 0;border-bottom:1px solid var(--wco-color-neutral-300, #e5e7eb)}.wco-contracts__signer-info{display:flex;flex-direction:column;padding:var(--wco-spacing-xxxs)}.wco-contracts__signer-info--removed{opacity:.4}.wco-contracts__signer-actions{display:flex;align-items:center;gap:8px;padding:var(--wco-spacing-xxxs)}.wco-contracts__signer-actions .wco-form-field{min-width:160px}.wco-contracts__signer-cards{display:flex;flex-direction:column;gap:12px;margin-top:16px}.wco-contracts__signer-card{padding:12px 16px;border:1px solid var(--wco-color-neutral-300, #e5e7eb);border-radius:8px;background:var(--wco-color-neutral-50, #f9fafb)}.wco-contracts__signer-card-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.wco-contracts__signer-card-row+.wco-contracts__signer-card-row{margin-top:4px}.wco-contracts__signer-card-row .material-icons{font-size:16px}.wco-contracts__role-tag{display:inline-flex;align-items:center;padding:2px 12px;border:1px solid var(--wco-color-neutral-300, #e5e7eb);border-radius:16px;background:var(--wco-color-neutral-100, #f3f4f6);color:var(--wco-color-neutral-900, #111827);font-size:12px;font-weight:600;white-space:nowrap}.wco-contracts__menu-wrapper{display:flex;justify-content:flex-end}.wco-contracts__menu{position:absolute;z-index:10;min-width:230px;padding:4px 0;background:#fff;border-radius:8px;box-shadow:0 4px 16px #00000029}.wco-contracts__menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 16px;border:0;background:none;cursor:pointer;font-size:14px;color:var(--wco-color-neutral-900, #111827)}.wco-contracts__menu-item:hover:not(:disabled){background:var(--wco-color-neutral-50, #f9fafb)}.wco-contracts__menu-item:disabled{opacity:.4;cursor:default}.wco-contracts table td{width:25%}.wco-contracts table td:nth-child(1){width:50%}.wco-contracts .iconEmpty{font-size:61px!important}.wco-contracts .bold-600{font-weight:600!important}.wco-contracts .header-modal{margin-top:-24px}\n"] }]
3648
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { contracts: [{
3649
+ type: Input
3650
+ }], templates: [{
3651
+ type: Input
3652
+ }], signers: [{
3653
+ type: Input
3654
+ }], roles: [{
3655
+ type: Input
3656
+ }], title: [{
3657
+ type: Input
3658
+ }], emptyMessage: [{
3659
+ type: Input
3660
+ }], emptyIcon: [{
3661
+ type: Input
3662
+ }], loading: [{
3663
+ type: Input
3664
+ }], generating: [{
3665
+ type: Input
3666
+ }], page: [{
3667
+ type: Input
3668
+ }], totalPages: [{
3669
+ type: Input
3670
+ }], generateContract: [{
3671
+ type: Output
3672
+ }], downloadDocument: [{
3673
+ type: Output
3674
+ }], signersRequested: [{
3675
+ type: Output
3676
+ }], pageChange: [{
3677
+ type: Output
3678
+ }], generateModal: [{
3679
+ type: ViewChild,
3680
+ args: ['generateModal']
3681
+ }], signersModal: [{
3682
+ type: ViewChild,
3683
+ args: ['signersModal']
3684
+ }], closeMenu: [{
3685
+ type: HostListener,
3686
+ args: ['document:click']
3687
+ }, {
3688
+ type: HostListener,
3689
+ args: ['window:resize']
3690
+ }] } });
3691
+
3349
3692
  /*
3350
3693
  * Public API Surface of ngx-fenixds
3351
3694
  */
@@ -3354,5 +3697,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3354
3697
  * Generated bundle index. Do not edit.
3355
3698
  */
3356
3699
 
3357
- export { DatepickerComponent, MsgBoxFeedbackComponent, PaginationComponent, PreviewFileComponent, SmartSelectComponent, SmartSelectOptionComponent, StepComponent, StepperComponent, StepperGroupComponent, SubTabsComponent, TableComponent, TabsComponent, TimelineComponent, UploadComponent, UserAvatarComponent, WcoModalAlertComponent, WcoToastComponent, WcoToastService };
3700
+ export { ContractsComponent, DatepickerComponent, MsgBoxFeedbackComponent, PaginationComponent, PreviewFileComponent, SmartSelectComponent, SmartSelectOptionComponent, StepComponent, StepperComponent, StepperGroupComponent, SubTabsComponent, TableComponent, TabsComponent, TimelineComponent, UploadComponent, UserAvatarComponent, WcoModalAlertComponent, WcoToastComponent, WcoToastService };
3358
3701
  //# sourceMappingURL=wizco-fenixds-ngx.mjs.map