@@ -96,6 +96,8 @@ export class ProductWorkspaceComponent implements OnInit {
9696 readonly manufacturersByProduct = signal < OemCode [ ] > ( [ ] ) ;
9797 readonly selectedImageForDelete = signal < MediaImageItem | null > ( null ) ;
9898
99+ readonly modifiedTabs = signal < Set < FormTab > > ( new Set < FormTab > ( ) ) ;
100+
99101 readonly product = signal < ProductResponse > ( initialProductPayload ) ;
100102 readonly productForm = signal < UpdateProductPayload > ( defaultUpdatePayload ( ) ) ;
101103
@@ -241,8 +243,17 @@ export class ProductWorkspaceComponent implements OnInit {
241243 return false ;
242244 }
243245
244- updateField ( field : string , val : string ) : void {
246+ private markCurrentTabAsModified ( ) : void {
245247 this . isFormDirty . set ( true ) ;
248+ this . modifiedTabs . update ( ( tabs ) => {
249+ const newTabs = new Set ( tabs ) ;
250+ newTabs . add ( this . activeTab ( ) ) ;
251+ return newTabs ;
252+ } ) ;
253+ }
254+
255+ updateField ( field : string , val : string ) : void {
256+ this . markCurrentTabAsModified ( ) ;
246257 const fieldMapping : Record < string , keyof UpdateProductPayload > = {
247258 name : 'name' ,
248259 internal_code : 'internal_code' ,
@@ -270,7 +281,7 @@ export class ProductWorkspaceComponent implements OnInit {
270281 }
271282
272283 updateBooleanField ( field : string , val : boolean ) : void {
273- this . isFormDirty . set ( true ) ;
284+ this . markCurrentTabAsModified ( ) ;
274285 if ( field === 'active' ) {
275286 this . productForm . update ( ( p ) => ( { ...p , active : val } ) ) ;
276287 } else if ( field === 'featured' ) {
@@ -279,7 +290,7 @@ export class ProductWorkspaceComponent implements OnInit {
279290 }
280291
281292 updateNumberField ( field : string , valStr : string ) : void {
282- this . isFormDirty . set ( true ) ;
293+ this . markCurrentTabAsModified ( ) ;
283294 const num = parseFloat ( valStr ) || 0 ;
284295 const fieldMapping : Record < string , keyof UpdateProductPayload > = {
285296 weight : 'weight' ,
@@ -314,7 +325,7 @@ export class ProductWorkspaceComponent implements OnInit {
314325 }
315326
316327 updateNullableNumberField ( field : string , valStr : string ) : void {
317- this . isFormDirty . set ( true ) ;
328+ this . markCurrentTabAsModified ( ) ;
318329 const val = valStr . trim ( ) === '' ? null : parseFloat ( valStr ) ;
319330 if ( field === 'promotional_price' ) {
320331 this . productForm . update ( ( p ) => ( {
@@ -347,7 +358,7 @@ export class ProductWorkspaceComponent implements OnInit {
347358 }
348359
349360 updateDescription ( val : string ) : void {
350- this . isFormDirty . set ( true ) ;
361+ this . markCurrentTabAsModified ( ) ;
351362 this . productForm . update ( ( p ) => ( { ...p , description : val } ) ) ;
352363 }
353364
@@ -356,7 +367,7 @@ export class ProductWorkspaceComponent implements OnInit {
356367 }
357368
358369 onInventoriesChange ( inventories : UpdateProductInventoryPayload [ ] ) : void {
359- this . isFormDirty . set ( true ) ;
370+ this . markCurrentTabAsModified ( ) ;
360371 this . productForm . update ( ( p ) => ( { ...p , inventories } ) ) ;
361372 if ( this . errors ( ) [ 'inventories' ] ) {
362373 this . errors . update ( ( e ) => {
@@ -369,7 +380,7 @@ export class ProductWorkspaceComponent implements OnInit {
369380
370381 toggleBackorder ( ) : void {
371382 if ( this . isReadOnly ( ) ) return ;
372- this . isFormDirty . set ( true ) ;
383+ this . markCurrentTabAsModified ( ) ;
373384 this . productForm . update ( ( p ) => {
374385 const invs = p . inventories || [ ] ;
375386 const first = invs [ 0 ] || { warehouse_id : '' , quantity : 0 } ;
@@ -398,15 +409,15 @@ export class ProductWorkspaceComponent implements OnInit {
398409 oem_code_ids : [ newId , ...( pf . oem_code_ids || this . product ( ) . oem_codes . map ( ( o ) => o . id ) ) ] ,
399410 } ) ) ;
400411
401- this . isFormDirty . set ( true ) ;
412+ this . markCurrentTabAsModified ( ) ;
402413 }
403414
404415 setPrimaryOem ( id : string ) : void {
405416 this . product . update ( ( p ) => ( {
406417 ...p ,
407418 oem_codes : p . oem_codes . map ( ( o ) => ( { ...o , is_primary : o . id === id } ) ) ,
408419 } ) ) ;
409- this . isFormDirty . set ( true ) ;
420+ this . markCurrentTabAsModified ( ) ;
410421 }
411422
412423 removeOemCode ( id : string ) : void {
@@ -422,7 +433,7 @@ export class ProductWorkspaceComponent implements OnInit {
422433 ) ,
423434 } ) ) ;
424435
425- this . isFormDirty . set ( true ) ;
436+ this . markCurrentTabAsModified ( ) ;
426437 }
427438
428439 toggleOemStatus ( id : string ) : void {
@@ -448,7 +459,7 @@ export class ProductWorkspaceComponent implements OnInit {
448459 product_code_ids : [ ...( pf . product_code_ids || this . product ( ) . codes . map ( ( c ) => c . id ) ) , newId ] ,
449460 } ) ) ;
450461
451- this . isFormDirty . set ( true ) ;
462+ this . markCurrentTabAsModified ( ) ;
452463 }
453464
454465 removeProductCode ( id : string ) : void {
@@ -464,7 +475,7 @@ export class ProductWorkspaceComponent implements OnInit {
464475 ) ,
465476 } ) ) ;
466477
467- this . isFormDirty . set ( true ) ;
478+ this . markCurrentTabAsModified ( ) ;
468479 }
469480
470481 toggleProductCodeStatus ( id : string ) : void {
@@ -498,7 +509,7 @@ export class ProductWorkspaceComponent implements OnInit {
498509 ] ,
499510 } ) ) ;
500511
501- this . isFormDirty . set ( true ) ;
512+ this . markCurrentTabAsModified ( ) ;
502513 }
503514
504515 removeEquivalent ( id : string ) : void {
@@ -514,7 +525,7 @@ export class ProductWorkspaceComponent implements OnInit {
514525 ) . filter ( ( eqId ) => eqId !== id ) ,
515526 } ) ) ;
516527
517- this . isFormDirty . set ( true ) ;
528+ this . markCurrentTabAsModified ( ) ;
518529 }
519530
520531 toggleEquivalentStatus ( id : string ) : void {
@@ -553,7 +564,7 @@ export class ProductWorkspaceComponent implements OnInit {
553564 ] ,
554565 } ) ) ;
555566
556- this . isFormDirty . set ( true ) ;
567+ this . markCurrentTabAsModified ( ) ;
557568 }
558569
559570 removeVehicleApplication ( id : string ) : void {
@@ -569,7 +580,7 @@ export class ProductWorkspaceComponent implements OnInit {
569580 ) ,
570581 } ) ) ;
571582
572- this . isFormDirty . set ( true ) ;
583+ this . markCurrentTabAsModified ( ) ;
573584 }
574585
575586 toggleVehicleStatus ( id : string ) : void {
@@ -643,7 +654,7 @@ export class ProductWorkspaceComponent implements OnInit {
643654 supplier_ids : [ ...( pf . supplier_ids || this . product ( ) . suppliers . map ( ( s ) => s . id ) ) , newId ] ,
644655 } ) ) ;
645656
646- this . isFormDirty . set ( true ) ;
657+ this . markCurrentTabAsModified ( ) ;
647658 }
648659
649660 removeSupplier ( id : string ) : void {
@@ -659,7 +670,7 @@ export class ProductWorkspaceComponent implements OnInit {
659670 ) ,
660671 } ) ) ;
661672
662- this . isFormDirty . set ( true ) ;
673+ this . markCurrentTabAsModified ( ) ;
663674 }
664675
665676 setPreferentialSupplier ( id : string ) : void {
@@ -670,7 +681,7 @@ export class ProductWorkspaceComponent implements OnInit {
670681 preferred : s . id === id ,
671682 } ) ) ,
672683 } ) ) ;
673- this . isFormDirty . set ( true ) ;
684+ this . markCurrentTabAsModified ( ) ;
674685 }
675686
676687 toggleSupplierStatus ( id : string ) : void {
@@ -680,7 +691,7 @@ export class ProductWorkspaceComponent implements OnInit {
680691
681692 toggleTag ( tagId : string ) : void {
682693 if ( this . isReadOnly ( ) ) return ;
683- this . isFormDirty . set ( true ) ;
694+ this . markCurrentTabAsModified ( ) ;
684695
685696 this . product . update ( ( p ) => {
686697 const exists = p . tags . some ( ( t ) => t . id === tagId ) ;
@@ -792,15 +803,71 @@ export class ProductWorkspaceComponent implements OnInit {
792803
793804 this . isSaving . set ( true ) ;
794805 const id = this . route . snapshot . paramMap . get ( 'id' ) ;
795- const payload = this . productForm ( ) ;
806+ const fullPayload = this . productForm ( ) ;
807+ const modified = this . modifiedTabs ( ) ;
808+
809+ const payload : Partial < UpdateProductPayload > = { } ;
810+
811+ if ( modified . has ( 'geral' ) || modified . has ( 'classification' ) || modified . has ( 'logistics' ) || modified . has ( 'visibility' ) ) {
812+ if ( fullPayload . name !== undefined ) payload . name = fullPayload . name ;
813+ if ( fullPayload . slug !== undefined ) payload . slug = fullPayload . slug ;
814+ if ( fullPayload . short_description !== undefined ) payload . short_description = fullPayload . short_description ;
815+ if ( fullPayload . description !== undefined ) payload . description = fullPayload . description ;
816+ if ( fullPayload . category_id !== undefined ) payload . category_id = fullPayload . category_id ;
817+ if ( fullPayload . manufacturer_id !== undefined ) payload . manufacturer_id = fullPayload . manufacturer_id ;
818+ if ( fullPayload . part_origin_id !== undefined ) payload . part_origin_id = fullPayload . part_origin_id ;
819+ if ( fullPayload . status_id !== undefined ) payload . status_id = fullPayload . status_id ;
820+ if ( fullPayload . internal_code !== undefined ) payload . internal_code = fullPayload . internal_code ;
821+ if ( fullPayload . barcode !== undefined ) payload . barcode = fullPayload . barcode ;
822+ if ( fullPayload . unit_id !== undefined ) payload . unit_id = fullPayload . unit_id ;
823+ if ( fullPayload . weight !== undefined ) payload . weight = fullPayload . weight ;
824+ if ( fullPayload . height !== undefined ) payload . height = fullPayload . height ;
825+ if ( fullPayload . width !== undefined ) payload . width = fullPayload . width ;
826+ if ( fullPayload . length !== undefined ) payload . length = fullPayload . length ;
827+ if ( fullPayload . featured !== undefined ) payload . featured = fullPayload . featured ;
828+ if ( fullPayload . active !== undefined ) payload . active = fullPayload . active ;
829+ }
830+
831+ if ( modified . has ( 'comercial' ) ) {
832+ if ( fullPayload . price !== undefined ) payload . price = fullPayload . price ;
833+ }
834+
835+ if ( modified . has ( 'inventario' ) ) {
836+ if ( fullPayload . inventories !== undefined ) payload . inventories = fullPayload . inventories ;
837+ }
838+
839+ if ( modified . has ( 'oem' ) ) {
840+ if ( fullPayload . oem_code_ids !== undefined ) payload . oem_code_ids = fullPayload . oem_code_ids ;
841+ }
842+
843+ if ( modified . has ( 'codigos' ) ) {
844+ if ( fullPayload . product_code_ids !== undefined ) payload . product_code_ids = fullPayload . product_code_ids ;
845+ }
846+
847+ if ( modified . has ( 'equivalentes' ) ) {
848+ if ( fullPayload . equivalent_product_ids !== undefined ) payload . equivalent_product_ids = fullPayload . equivalent_product_ids ;
849+ }
850+
851+ if ( modified . has ( 'compatibilidade' ) ) { // Veículos/Aplicações
852+ if ( fullPayload . application_ids !== undefined ) payload . application_ids = fullPayload . application_ids ;
853+ }
854+
855+ if ( modified . has ( 'fornecimento' ) ) {
856+ if ( fullPayload . supplier_ids !== undefined ) payload . supplier_ids = fullPayload . supplier_ids ;
857+ }
858+
859+ if ( modified . has ( 'tags' ) ) {
860+ if ( fullPayload . tag_ids !== undefined ) payload . tag_ids = fullPayload . tag_ids ;
861+ }
796862
797863 // console.log('[SAVE PRODUCT UPDATE]', payload);
798864 // return;
799865
800- this . productService . update ( id ! , payload ) . subscribe ( {
866+ this . productService . update ( id ! , payload as UpdateProductPayload ) . subscribe ( {
801867 next : ( response ) => {
802868 this . isSaving . set ( false ) ;
803869 this . isFormDirty . set ( false ) ;
870+ this . modifiedTabs . set ( new Set < FormTab > ( ) ) ;
804871 this . toastService . success ( response . message , 'Informações atualizadas no sistema.' ) ;
805872
806873 const prodData = response . data || response ;
0 commit comments