Skip to content

Commit b773461

Browse files
committed
FIX Ticket#831737 unable to add free product to cart from details
1 parent ea4492b commit b773461

3 files changed

Lines changed: 146 additions & 108 deletions

File tree

src/app/pages/product-details/product-details.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ <h5 class="md:text-3xl lg:text-4xl font-semibold tracking-tight text-primary-100
140140
</ul>
141141
@if(check_logged){
142142
@if (!isCustom()) {
143-
<button type="button" (click)="openDrawer()" [disabled]="!PURCHASE_ENABLED" [ngClass]="!PURCHASE_ENABLED ? 'opacity-50' : 'hover:bg-primary-50'" class="hidden md:flex w-fit m-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
143+
<button type="button" (click)="openDrawer()" [disabled]="!PURCHASE_ENABLED || productAlreadyInCart" [ngClass]="!PURCHASE_ENABLED || productAlreadyInCart ? 'opacity-50' : 'hover:bg-primary-50'" class="hidden md:flex w-fit m-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
144144
<svg class="w-3.5 h-3.5 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 21">
145145
<path d="M15 12a1 1 0 0 0 .962-.726l2-7A1 1 0 0 0 17 3H3.77L3.175.745A1 1 0 0 0 2.208 0H1a1 1 0 0 0 0 2h.438l.6 2.255v.019l2 7 .746 2.986A3 3 0 1 0 9 17a2.966 2.966 0 0 0-.184-1h2.368c-.118.32-.18.659-.184 1a3 3 0 1 0 3-3H6.78l-.5-2H15Z"/>
146146
</svg>
@@ -158,7 +158,7 @@ <h5 class="md:text-3xl lg:text-4xl font-semibold tracking-tight text-primary-100
158158
</div>
159159
@if(check_logged) {
160160
@if (!isCustom()) {
161-
<button type="button" (click)="openDrawer()" [disabled]="!PURCHASE_ENABLED" [ngClass]="!PURCHASE_ENABLED ? 'opacity-50' : 'hover:bg-primary-50'" class="flex md:hidden justify-end w-fit m-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
161+
<button type="button" (click)="openDrawer()" [disabled]="!PURCHASE_ENABLED || productAlreadyInCart" [ngClass]="!PURCHASE_ENABLED || productAlreadyInCart ? 'opacity-50' : 'hover:bg-primary-50'" class="flex md:hidden justify-end w-fit m-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
162162
<svg class="w-3.5 h-3.5 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 21">
163163
<path d="M15 12a1 1 0 0 0 .962-.726l2-7A1 1 0 0 0 17 3H3.77L3.175.745A1 1 0 0 0 2.208 0H1a1 1 0 0 0 0 2h.438l.6 2.255v.019l2 7 .746 2.986A3 3 0 1 0 9 17a2.966 2.966 0 0 0-.184-1h2.368c-.118.32-.18.659-.184 1a3 3 0 1 0 3-3H6.78l-.5-2H15Z"/>
164164
</svg>

src/app/pages/product-details/product-details.component.ts

Lines changed: 123 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export class ProductDetailsComponent implements OnInit {
8383

8484
orgInfo:any=undefined;
8585
showQuoteModal:boolean = false;
86+
productAlreadyInCart:boolean=false;
8687

8788
protected readonly faScaleBalanced = faScaleBalanced;
8889
protected readonly faArrowProgress = faArrowProgress;
@@ -140,7 +141,25 @@ export class ProductDetailsComponent implements OnInit {
140141
} else if(ev.type === 'CloseQuoteRequest'){
141142
this.showQuoteModal=false;
142143
this.cdr.detectChanges();
143-
}
144+
} else if (ev.type == 'RemovedCartItem'){
145+
this.cartService.getShoppingCart().then(data => {
146+
const exists = data.some((item: any) => item.id === this.productOff?.id);
147+
if (exists) {
148+
this.productAlreadyInCart=true;
149+
} else {
150+
this.productAlreadyInCart=false;
151+
}
152+
})
153+
} else if (ev.type == 'AddedCartItem'){
154+
this.cartService.getShoppingCart().then(data => {
155+
const exists = data.some((item: any) => item.id === this.productOff?.id);
156+
if (exists) {
157+
this.productAlreadyInCart=true;
158+
} else {
159+
this.productAlreadyInCart=false;
160+
}
161+
})
162+
}
144163
})
145164
}
146165

@@ -182,7 +201,7 @@ export class ProductDetailsComponent implements OnInit {
182201
}
183202
}
184203

185-
ngOnInit() {
204+
async ngOnInit() {
186205
initFlowbite();
187206
let aux = this.localStorage.getObject('login_items') as LoginInfo;
188207
if(JSON.stringify(aux) != '{}' && (((aux.expire - moment().unix())-4) > 0)) {
@@ -201,124 +220,122 @@ export class ProductDetailsComponent implements OnInit {
201220
this.cdr.detectChanges();
202221
}
203222
window.scrollTo(0, 0);
223+
let cart = await this.cartService.getShoppingCart();
224+
const exists = cart.some((item: any) => item.id === this.productOff?.id);
225+
if (exists) {
226+
this.productAlreadyInCart=true;
227+
} else {
228+
this.productAlreadyInCart=false;
229+
}
204230
this.id = this.route.snapshot.paramMap.get('id');
205231
console.log('--- Details ID:')
206232
console.log(this.id)
207-
this.api.getProductById(this.id).then(prod => {
208-
console.log('prod')
209-
console.log(prod)
210-
this.api.getProductSpecification(prod.productSpecification.id).then(spec => {
211-
this.prodSpec=spec;
212-
this.getOwner();
213-
let attachment = spec.attachment
214-
console.log(spec.attachment)
215-
let prodPrices: any[] | undefined= prod.productOfferingPrice;
216-
let prices: any[]=[];
217-
if(prodPrices!== undefined){
218-
for(let j=0; j < prodPrices.length; j++){
219-
this.api.getProductPrice(prodPrices[j].id).then(price => {
220-
prices.push(price);
221-
console.log(price)
222-
if(price.priceType == 'custom'){
223-
this.checkCustom = true;
224-
}
225-
})
233+
let prod = await this.api.getProductById(this.id);
234+
let spec = await this.api.getProductSpecification(prod.productSpecification.id);
235+
this.prodSpec=spec;
236+
this.getOwner();
237+
let prodPrices: any[] | undefined= prod.productOfferingPrice;
238+
let prices: any[]=[];
239+
if(prodPrices!== undefined){
240+
for(let j=0; j < prodPrices.length; j++){
241+
this.api.getProductPrice(prodPrices[j].id).then(price => {
242+
prices.push(price);
243+
console.log(price)
244+
if(price.priceType == 'custom'){
245+
this.checkCustom = true;
226246
}
227-
}
228-
229-
if(this.prodSpec.productSpecCharacteristic != undefined) {
230-
// Avoid displaying the compliance credential
231-
this.prodChars = this.prodSpec.productSpecCharacteristic.filter((char: any) => {
232-
return char.name != 'Compliance:VC' && char.name != 'Compliance:SelfAtt'
233-
})
247+
})
248+
}
249+
}
234250

235-
console.log('-- prod spec')
236-
console.log(this.prodSpec.productSpecCharacteristic)
237-
238-
for(let i=0; i<certifications.length; i++){
239-
//Now we only show the certifications that are attached when creating/updating the product
240-
let compProf = this.prodSpec.productSpecCharacteristic.find((p => {
241-
return p.name === certifications[i].name
242-
}));
243-
if(compProf){
244-
let cert:any = certifications[i]
245-
cert.href = compProf.productSpecCharacteristicValue?.at(0)?.value
246-
this.complianceProf.push(certifications[i])
247-
}
248-
//Deleting certifications out of characteristics' array
249-
const index = this.prodChars.findIndex(item => item.name === certifications[i].name);
250-
if(index!==-1){
251-
this.prodChars.splice(index, 1);
252-
}
253-
}
254-
}
255-
if(this.prodSpec.serviceSpecification != undefined){
256-
for(let j=0; j < this.prodSpec.serviceSpecification.length; j++){
257-
this.api.getServiceSpec(this.prodSpec.serviceSpecification[j].id).then(serv => {
258-
this.serviceSpecs.push(serv);
259-
})
260-
}
261-
}
262-
if(this.prodSpec.resourceSpecification != undefined){
263-
for(let j=0; j < this.prodSpec.resourceSpecification.length; j++){
264-
this.api.getResourceSpec(this.prodSpec.resourceSpecification[j].id).then(res => {
265-
this.resourceSpecs.push(res);
266-
})
267-
}
268-
}
251+
if(this.prodSpec.productSpecCharacteristic != undefined) {
252+
// Avoid displaying the compliance credential
253+
this.prodChars = this.prodSpec.productSpecCharacteristic.filter((char: any) => {
254+
return char.name != 'Compliance:VC' && char.name != 'Compliance:SelfAtt'
255+
})
269256

270-
console.log('serv specs')
271-
console.log(this.serviceSpecs)
272-
this.productOff={
273-
id: prod.id,
274-
name: prod.name,
275-
category: prod.category,
276-
description: prod.description,
277-
lastUpdate: prod.lastUpdate,
278-
attachment: attachment,
279-
productOfferingPrice: prices,
280-
productSpecification: prod.productSpecification,
281-
productOfferingTerm: prod.productOfferingTerm,
282-
serviceLevelAgreement: prod.serviceLevelAgreement,
283-
version: prod.version
257+
for(let i=0; i<certifications.length; i++){
258+
//Now we only show the certifications that are attached when creating/updating the product
259+
let compProf = this.prodSpec.productSpecCharacteristic.find((p => {
260+
return p.name === certifications[i].name
261+
}));
262+
if(compProf){
263+
let cert:any = certifications[i]
264+
cert.href = compProf.productSpecCharacteristicValue?.at(0)?.value
265+
this.complianceProf.push(certifications[i])
284266
}
285-
this.category = this.productOff?.category?.at(0)?.name ?? 'none';
286-
this.categories = this.productOff?.category;
287-
this.price = this.productOff?.productOfferingPrice?.at(0)?.price?.value + ' ' + this.productOff?.productOfferingPrice?.at(0)?.price?.unit ?? 'n/a';
288-
289-
let profile = this.productOff?.attachment?.filter(item => item.name === 'Profile Picture') ?? [];
290-
console.log('profile...')
291-
console.log(profile)
292-
if(profile.length==0){
293-
this.images = this.productOff?.attachment?.filter(item => item.attachmentType === 'Picture') ?? [];
294-
this.attatchments = this.productOff?.attachment?.filter(item => item.attachmentType != 'Picture') ?? [];
295-
} else {
296-
this.images = profile;
297-
this.attatchments = this.productOff?.attachment?.filter(item => item.name != 'Profile Picture') ?? [];
267+
//Deleting certifications out of characteristics' array
268+
const index = this.prodChars.findIndex(item => item.name === certifications[i].name);
269+
if(index!==-1){
270+
this.prodChars.splice(index, 1);
298271
}
272+
}
273+
}
274+
if(this.prodSpec.serviceSpecification != undefined){
275+
for(let j=0; j < this.prodSpec.serviceSpecification.length; j++){
276+
this.api.getServiceSpec(this.prodSpec.serviceSpecification[j].id).then(serv => {
277+
this.serviceSpecs.push(serv);
278+
})
279+
}
280+
}
281+
if(this.prodSpec.resourceSpecification != undefined){
282+
for(let j=0; j < this.prodSpec.resourceSpecification.length; j++){
283+
this.api.getResourceSpec(this.prodSpec.resourceSpecification[j].id).then(res => {
284+
this.resourceSpecs.push(res);
285+
})
286+
}
287+
}
299288

300-
this.licenseTerm = this.productOff?.productOfferingTerm?.find(
301-
element => element.name === 'License'
302-
);
289+
this.productOff={
290+
id: prod.id,
291+
name: prod.name,
292+
category: prod.category,
293+
description: prod.description,
294+
lastUpdate: prod.lastUpdate,
295+
attachment: spec.attachment,
296+
productOfferingPrice: prices,
297+
productSpecification: prod.productSpecification,
298+
productOfferingTerm: prod.productOfferingTerm,
299+
serviceLevelAgreement: prod.serviceLevelAgreement,
300+
version: prod.version
301+
}
302+
console.log('-------- producto')
303+
console.log(this.productOff)
304+
this.cdr.detectChanges();
305+
this.category = this.productOff?.category?.at(0)?.name ?? 'none';
306+
this.categories = this.productOff?.category;
307+
this.price = this.productOff?.productOfferingPrice?.at(0)?.price?.value + ' ' + this.productOff?.productOfferingPrice?.at(0)?.price?.unit ?? 'n/a';
308+
309+
let profile = this.productOff?.attachment?.filter(item => item.name === 'Profile Picture') ?? [];
310+
console.log('profile...')
311+
console.log(profile)
312+
if(profile.length==0){
313+
this.images = this.productOff?.attachment?.filter(item => item.attachmentType === 'Picture') ?? [];
314+
this.attatchments = this.productOff?.attachment?.filter(item => item.attachmentType != 'Picture') ?? [];
315+
} else {
316+
this.images = profile;
317+
this.attatchments = this.productOff?.attachment?.filter(item => item.name != 'Profile Picture') ?? [];
318+
}
303319

304-
if(this.prodSpec.productSpecCharacteristic != undefined) {
320+
this.licenseTerm = this.productOff?.productOfferingTerm?.find(
321+
element => element.name === 'License'
322+
);
305323

306-
// Find if there is a self attestement
307-
let selfAttObj = this.prodSpec.productSpecCharacteristic.find((p => {
308-
return p.name === `Compliance:SelfAtt`
309-
}));
324+
if(this.prodSpec.productSpecCharacteristic != undefined) {
310325

311-
if(selfAttObj){
312-
this.selfAtt = selfAttObj.productSpecCharacteristicValue?.at(0)?.value
313-
}
314-
}
326+
// Find if there is a self attestement
327+
let selfAttObj = this.prodSpec.productSpecCharacteristic.find((p => {
328+
return p.name === `Compliance:SelfAtt`
329+
}));
315330

316-
//Hardcoding compliance lever for the moment
317-
this.complianceLevel = this.api.getComplianceLevel(this.prodSpec);
318-
this.complianceDescription = this.getComplianceDescription();
319-
})
320-
})
331+
if(selfAttObj){
332+
this.selfAtt = selfAttObj.productSpecCharacteristicValue?.at(0)?.value
333+
}
334+
}
321335

336+
//Hardcoding compliance lever for the moment
337+
this.complianceLevel = this.api.getComplianceLevel(this.prodSpec);
338+
this.complianceDescription = this.getComplianceDescription();
322339
}
323340

324341
toggleQuoteModal(){

src/app/shared/price-plan-drawer/price-plan-drawer.component.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ export class PricePlanDrawerComponent implements OnInit, OnDestroy {
9494
document.addEventListener('keydown', this.handleEscape.bind(this));
9595
// Configurar los términos y condiciones
9696
this.tsAndCs = { description: '' };
97+
console.log('---- producto')
98+
console.log(this.productOff)
9799

98100
this.productOff?.productOfferingTerm?.forEach((term) => {
99101
console.log(term.name)
@@ -158,6 +160,25 @@ export class PricePlanDrawerComponent implements OnInit, OnDestroy {
158160
}
159161
console.log(this.tsAndCs)
160162
}
163+
if (changes['productOff'] && changes['productOff'].currentValue) {
164+
console.log('Changes...')
165+
console.log(this.productOff)
166+
167+
this.isFree = this.productOff?.productOfferingPrice?.length === 0;
168+
169+
if (this.isFree) {
170+
this.form.get('selectedPricePlan')?.setValue({});
171+
this.characteristics = this.prodSpec.productSpecCharacteristic || [];
172+
this.filterCharacteristics();
173+
}
174+
175+
let profile = this.productOff?.attachment?.filter(item => item.name === 'Profile Picture') ?? [];
176+
if(profile.length==0){
177+
this.images = this.productOff?.attachment?.filter(item => item.attachmentType === 'Picture') ?? [];
178+
} else {
179+
this.images = profile;
180+
}
181+
}
161182
}
162183

163184
ngOnDestroy(): void {

0 commit comments

Comments
 (0)